异步调用 WCF 服务并在新任务中等待它

Call a WCF service Asynchronously and Wait for it in a New Task

我是基于任务的编程的新手。我必须异步调用 WCF 服务并启动一个任务来等待它,因为我不想在相同的方法中等待,所以我编写了类似这样的代码

void MyMainMethod()
{
   for(int j=0;j<10; j++)
   {

      int I = 100;
      Task<response> res =  _client.GetValueAsnc(request);

       //Do some work

       Task.Run(()=> WaitForResponse(res , I));
    }
}

Async Task WaitForResponse(Task<response> res , int I)
{
   await res;

   if(res.responsecode == "Success")
   {
      //udatateDB...
   }
 
   else
   {
      //update DB with Error Message..
   }
}

那样的话,如果我在一个循环中调用该服务 10 次,它将启动 10 个任务并给我响应,而不是在 MyMainMethod() 中等待响应,我为每个请求启动一个单独的任务。

如果这是正确的方法,或者我在这里犯了一些重大错误,请告诉我,如果我需要更多细节来解释这个问题。

提前致谢。

你努力实现的是一件好事。不阻塞某些主线程是个好主意,您这样做的方式将会奏效。

但是,如果你这样做,你必须手动控制任务的数量。您可能不希望数字太高,否则过多的并行性可能会影响性能。

.net 中有 classes 有助于通过所谓的线程池管理任务队列。 您使用已知的最大线程数配置线程池,然后将任务排队到池中。线程池 class 负责清空队列并将任务分配给池中的空闲线程。

您可以了解有关线程池的更多信息here on ms docs

下面的示例来自 MS 文档站点。

using System;
using System.Threading;

public class Example 
{
    public static void Main() 
    {
        // Queue the task.
        ThreadPool.QueueUserWorkItem(ThreadProc);
        Console.WriteLine("Main thread does some work, then sleeps.");
        Thread.Sleep(1000);

        Console.WriteLine("Main thread exits.");
    }

    // This thread procedure performs the task.
    static void ThreadProc(Object stateInfo) 
    {
        // No state object was passed to QueueUserWorkItem, so stateInfo is null.
        Console.WriteLine("Hello from the thread pool.");
    }
}
// The example displays output like the following:
//       Main thread does some work, then sleeps.
//       Hello from the thread pool.
//       Main thread exits.

为什么不在线程池上使用任务并行库。

class Client
{
    internal async Task<string> GetValueAsnc()
    {
        Console.WriteLine("GetValueAsync");
        await Task.Delay(TimeSpan.FromSeconds(2));
        return "success";
    }
}
class Program
{
    private static readonly Client _client = new Client();

    static void Main(string[] args)
    {
        var tasks = new List<Task>();
        for (int j = 0; j < 10; j++)
        {
            tasks.Add(WaitForResponse());
        }

        Task.WhenAll(tasks);
        Console.WriteLine("Tasks finished");
        Console.ReadLine();
    }

    static async Task WaitForResponse()
    {
        var res = await _client.GetValueAsnc();

        if (res == "Success")
        {
            //udatateDB...
        }

        else
        {
            //update DB with Error Message..
        }
    }
}

它api比ThreadPool更好,这样就不用担心线程饥饿