【发布时间】:2019-01-18 16:17:51
【问题描述】:
我有一个 WPF 应用程序做一些非常简单的事情。我只是让它触发4 对基本@987654323@ 的请求。
private async Task MultipleWcfCalls()
{
ServiceReference.Service1Client _proxy = new ServiceReference.Service1Client();
_proxy.Open();
var t1 = _proxy.GetDataAsync(0);
var t2 = _proxy.GetDataAsync(0);
var t3 = _proxy.GetDataAsync(0);
var t4 = _proxy.GetDataAsync(0);
await Task.WhenAll(t1, t2, t3, t4);
}
我的服务是做经典的Task.Delay(3000)。
public async Task<string> GetDataAsync(int value)
{
int other = 0;
int workerThreadsAvail = 0;
ThreadPool.GetMinThreads(out workerThreadsAvail, out other);
await Task.Delay(3000);
return workerThreadsAvail.ToString();
}
我希望4 请求被触发,而3 秒后,我希望所有四个请求都返回。嗯,实际发生的情况是所有四个请求都通过网络发送,前三个请求将返回,然后最后一个请求将在之后返回 3。
节流
起初我以为这是我的问题。好吧,我添加了<serviceThrottling maxConcurrentCalls="10"/> int 我的web.config 并没有任何区别。所以,然后我读到它可能是我使用代理达到的连接限制,所以我将ServicePointManager.DefaultConnectionLimit=10; 添加到我的 WPF 应用程序中。
线程饥饿
然后,我不断遇到线程饥饿。因此,作为一个测试,我尝试将最小线程数设置为20,以确保我有足够的速度来处理4 请求。我将此添加到我的 WPF 应用程序ThreadPool.SetMinThreads(20, 20);。因此,为了确认有大量工作线程可用于处理请求,我决定让我的服务调用在进程开始时返回可用线程的数量。每个请求都返回19 或20。
使用 Fiddler,我可以确认所有 4 请求都已从 WPF(客户端)应用程序通过网络发送。现在,我的 Wcf 正在使用 basicHttpBinding,所以它在 Per Call 实例模式下运行,所以并发模式应该无关紧要,但为了安全起见,我添加了 [ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Multiple)]。
我已经使用System.Diagnostics.XmlWriterTraceListener 进行了一些堆栈跟踪,我可以确认我收到了3 请求同时记录(几乎),然后第四个请求在 3 秒后被记录。
Wcf 托管在IIS。如果需要更多信息,请告诉我,我会尽快添加。
根据要求,这是我的 WCF 界面。
namespace SampleWCF
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
[ServiceContract]
public interface IService1
{
[OperationContract]
System.Threading.Tasks.Task<string> GetData(int value);
}
}
【问题讨论】:
-
这是否与处理器中的核心有关,quad = 4, 4-1 = 3 thread。
-
@AnirudhaGupta 我不太了解这些东西,但我相信我在六核处理器上运行。
-
如果在 WCF 代码中执行
await Task.Delay(3000).ConfigureAwait(false)是否相同?你能检查一下那里是否有任何同步上下文(SynchronizationContext.Current?.GetType()?.Name)吗? -
另外请注意,WCF 和 WPF 中的异步是完全独立的——您可以调用同步的异步方法,反之亦然。所以忽略 WPF 部分,这都是关于 WCF 的。
-
@James,从您对 cmets 的回答来看,很明显这是特定于您的 IIS 配置的。很难在无法复制的情况下进一步发展。我建议您尝试
WorkerThreadPoolBehavior并确保服务在其自己的 IIS 应用程序池中运行。这是另一篇有用的 MSKB 文章,用于进一步排除故障:Contention, poor performance, and deadlocks when you make calls to Web services from an ASP.NET application。如果您找到它,请发布您自己的答案。
标签: c# multithreading wcf threadpool iis-8