【问题标题】:How to make a task complete before running another task如何在运行另一个任务之前完成一个任务
【发布时间】:2014-09-11 21:07:00
【问题描述】:

我正在使用 Microsoft Web API 2.2 客户端从 API 端点请求数据。获得数据后,我运行 x 个 DoSomeWork。我想确保在运行 DoSomeWork 函数之前先加载数据。

根据下面的代码,我期待以下输出。

“开始 GetSomething” “完成GetSomething” “开始工作#1” “开始工作#2”

但我得到以下信息 “开始GetSomething” “开始工作#1” “完成GetSomething” “开始工作#2”

    static void Main()
    {
        try
        {
            Task getSomethingTask = Task.Factory.StartNew(()=>GetSomething());
            getSomethingTask.Wait();
            Task[] tasks = new Task[2] {
                 Task.Facotry.StartNew(()=>DoSomeWork(1)),
                 Task.Facotry.StartNew(()=>DoSomeWork(2))
            };
            Task.WaitAll(tasks);
        }
        catch(Exception ex)
        {
           throw ex;
        }
    }
    static async Task GetSomething()
    {
        Console.WriteLine("Starting GetSomething");
        try
        {
            HttpClient client = new HttpClient();
            client.BaseAddress = new Uri(SOME_URL);
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            HttpResponseMessage response = await client.GetAsync("api/v1/somethings");
            somethingList = await response.Content.ReadAsAsync<SomeObject>();
        }
        catch (Exception)
        {

            throw;
        }
        Console.WriteLine("Done with GetSomething");
    }
    static async Task DoSomeWork(int workNumber)
    {
       Console.Writeline("Start work#" + workNumber);
    }

【问题讨论】:

    标签: c# asp.net-web-api task-parallel-library async-await


    【解决方案1】:

    在进行异步编程(即 I/O 绑定)时,您希望避免使用 StartNewWaitWaitAll。相反,几乎所有逻辑都使用asyncawait

    由于这是一个控制台应用程序,您确实需要一个 Wait 以便主线程不会退出。这应该是整个应用中唯一的Wait

    static void Main()
    {
      MainAsync().Wait();
    }
    
    static async Task MainAsync()
    {
      await GetSomethingAsync();
      await Task.WhenAll(DoSomeWorkAsync(1), DoSomeWorkAsync(2));
    }
    
    static async Task GetSomethingAsync()
    {
      Console.WriteLine("Starting GetSomething");
      HttpClient client = new HttpClient();
      ...
      HttpResponseMessage response = await client.GetAsync("api/v1/somethings");
      somethingList = await response.Content.ReadAsAsync<SomeObject>();
      Console.WriteLine("Done with GetSomething");
    }
    
    static async Task DoSomeWorkAsync(int workNumber)
    {
      Console.Writeline("Start work#" + workNumber);
    }
    

    您可能会发现我的async intro 很有帮助。

    【讨论】:

      【解决方案2】:

      我相信getSomethingTask 会立即结束,因为你不是awaiting GetSomething()

      试试这个:

      Task getSomethingTask = Task.Factory.StartNew(async () => await GetSomething());
      

      或者简单地说:

      GetSomething().Wait();
      

      虽然我认为通过创建一个新线程并立即在主线程上等待结果并没有真正获得任何好处。

      【讨论】:

        【解决方案3】:

        当您从线程调用await 时,您将控制权交还给其父线程。

        在这种情况下,这是您的违规行:

        HttpResponseMessage response = await client.GetAsync("api/v1/somethings");
        

        一旦您这样做,您的GetSomething 线程就会将控制权交还给Main() 线程,这就是您看到DoSomeWork 任务正在执行的原因。

        如果您摆脱 GetSomething 中的那些 await 调用并用同步调用替换它们,您将获得您想要的行为。

        有关详细信息,请参阅此处的 Microsoft 异步编程指南(尤其是第 6 步,其中谈到了await):http://msdn.microsoft.com/async

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-03-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-01-17
          • 1970-01-01
          • 1970-01-01
          • 2016-05-24
          相关资源
          最近更新 更多