it-swarm.dev

المتزامن في وحدة التحكم في التطبيق C #؟

لدي هذا الرمز البسيط:

public static async Task<int> SumTwoOperationsAsync()
{
    var firstTask = GetOperationOneAsync();
    var secondTask = GetOperationTwoAsync();
    return await firstTask + await secondTask;
}


private async Task<int> GetOperationOneAsync()
{
    await Task.Delay(500); // Just to simulate an operation taking time
    return 10;
}

private async Task<int> GetOperationTwoAsync()
{
    await Task.Delay(100); // Just to simulate an operation taking time
    return 5;
}

عظيم. هذا يجمع.

ولكن دعنا نقول أن لدي تطبيق وحدة التحكم وأريد تشغيل الكود أعلاه (استدعاء SumTwoOperationsAsync())

 static  void Main(string[] args)
        {
             SumTwoOperationsAsync();
        }

لكنني قرأت ذلك (عند استخدام sync) يجب أن أقوم بمزامنة طول الطريق up و down :

سؤال : هل هذا يعني أن وظيفتي Main يجب أن تكون مميزة بـ async؟

حسنًا لا يمكن أن يكون هناك خطأ في الترجمة:

لا يمكن وضع علامة على نقطة إدخال باستخدام معدل "async"

إذا فهمت الاشياء غير المتزامنة ، فستدخل سلسلة العمليات في الدالة Main ----> SumTwoOperationsAsync ----> ستدعو كلتا الدالتين وستكون خارج. ولكن حتى SumTwoOperationsAsync

ماذا ينقصني ؟

160
Royi Namir

في معظم أنواع المشاريع ، سينتهي async "up" و "down" في معالج الأحداث async void أو إرجاع Task إلى إطارك.

ومع ذلك ، لا تدعم تطبيقات Console هذا.

يمكنك إما القيام بـ Wait في المهمة التي تم إرجاعها:

static void Main()
{
  MainAsync().Wait();
  // or, if you want to avoid exceptions being wrapped into AggregateException:
  //  MainAsync().GetAwaiter().GetResult();
}

static async Task MainAsync()
{
  ...
}

أو يمكنك استخدام سياقك الخاص مثل السياق الذي كتبته :

static void Main()
{
  AsyncContext.Run(() => MainAsync());
}

static async Task MainAsync()
{
  ...
}

مزيد من المعلومات لتطبيقات async Console هي على مدونتي .

268
Stephen Cleary

هنا أبسط طريقة للقيام بذلك

static void Main(string[] args)
{
    Task t = MainAsync(args);
    t.Wait();
}

static async Task MainAsync(string[] args)
{
    await ...
}
87
Murilo Maciel Curti

كحل سريع ومجاني للغاية:

Task.Result

لن تسمح كل من Task.Result و Task.Wait بتحسين قابلية التوسع عند استخدامها مع I/O ، حيث سيتسبب ذلك في استمرار حظر مؤشر ترابط الاستدعاء في انتظار انتهاء I/O.

عندما تقوم بالاتصال .Result بشأن مهمة غير مكتملة ، يجب أن يجلس مؤشر الترابط الذي ينفذ الأسلوب وينتظر إكمال المهمة ، مما يمنع سلسلة الرسائل من القيام بأي عمل مفيد آخر في الوقت الحالي. هذا ينفي فائدة الطبيعة غير المتزامنة للمهمة.

notasync

2
Alberto

بلدي الحل. JSONServer هي فئة كتبتها لتشغيل خادم HttpListener في نافذة وحدة التحكم.

class Program
{
    public static JSONServer srv = null;

    static void Main(string[] args)
    {
        Console.WriteLine("NLPS Core Server");

        srv = new JSONServer(100);
        srv.Start();

        InputLoopProcessor();

        while(srv.IsRunning)
        {
            Thread.Sleep(250);
        }

    }

    private static async Task InputLoopProcessor()
    {
        string line = "";

        Console.WriteLine("Core NLPS Server: Started on port 8080. " + DateTime.Now);

        while(line != "quit")
        {
            Console.Write(": ");
            line = Console.ReadLine().ToLower();
            Console.WriteLine(line);

            if(line == "?" || line == "help")
            {
                Console.WriteLine("Core NLPS Server Help");
                Console.WriteLine("    ? or help: Show this help.");
                Console.WriteLine("    quit: Stop the server.");
            }
        }
        srv.Stop();
        Console.WriteLine("Core Processor done at " + DateTime.Now);

    }
}
1
Richard Keene