异步调用 WCF 服务并在新任务中等待它
Posted
技术标签:
【中文标题】异步调用 WCF 服务并在新任务中等待它【英文标题】:Call a WCF service Asynchronously and Wait for it in a New Task 【发布时间】:2021-06-20 12:34:49 【问题描述】:我是基于任务的编程的新手。我必须异步调用 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() 中等待响应,我将为每个请求启动一个单独的任务。
如果这是正确的方法,或者我在这里犯了一些重大错误,并且如果我需要更多细节来解释这个问题,请告诉我。
提前致谢。
【问题讨论】:
Duplex Services 怎么样? 【参考方案1】:您尝试实现的目标是一件好事。不阻塞某个主线程是个好主意,而且你这样做的方式会奏效。
但是,如果你这样做,你必须手动控制任务的数量。您可能不希望这个数字太高,否则过多的并行性可能会影响性能。
.net 中有一些类可以通过所谓的线程池来帮助管理任务队列。 您使用已知的最大线程数配置线程池,然后将任务排队到池中。线程池类负责清空队列并将任务分配给池中的空闲线程。
您可以了解更多关于线程池的信息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.
【讨论】:
好的,非常感谢......所以当我们说“但是,如果你这样做,你必须手动控制任务的数量。你可能不希望数字太高,否则太多的并行性可能会损害性能”所以我们如何在这种情况下控制任务数量以及当我们说数字太高时..什么数字可能太高..问我对这个基于任务的异步编程一无所知 过高的数字取决于任务的用途、可用的内核数等。例如,如果任务执行阻塞 CPU 密集型工作,则高于内核数(可能如果您有超线程,则为 2 倍)对性能没有帮助。任务数量没有简单的规则,最好在您实施的特定场景中进行一些测量。在某些情况下,如果您有很多任务执行大量异步工作,它们可以重用物理线程。这一切都由线程池管理,相当复杂。 谢谢 Mirronelli,我会试试这个...非常感谢【参考方案2】:为什么不在线程池上使用任务并行库。
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..
它有比ThreadPool更好的api,这样不用担心线程饥饿
【讨论】:
谢谢Cavecode,你能解释一下你的建议和我的代码之间的区别吗?这样我才能更理解它....非常感谢 您需要等待对Task.WhenAll
的呼叫...或者您需要使用Task.WaitAll
。
@renu 请在此处查看***.com/questions/1774670/c-sharp-threadpool-vs-tasks 任务只是线程池的包装器,对于大多数用例来说它更好,因为您不必担心控制活动线程数等细节
@CaveCoder 你能告诉我我在代码中遵循的方法是什么。是线程池吗……但我使用的任务有点混乱
@renu 在您的代码上您正在使用任务,只是不是在最正确的方式上,其他答案代码是 ThreadPool以上是关于异步调用 WCF 服务并在新任务中等待它的主要内容,如果未能解决你的问题,请参考以下文章