我已经迈出了使用WCF开发WINDOWS服务托管计算引擎的第一步。该服务运行良好,但它似乎只使用一个线程用于我的所有调用,但我需要它可扩展并使用多线程。
忽略代码中的所有跟踪,因为这是本应用程序人员的早期阶段。
它调用某些第三方软件(COM),在服务启动时将信息读入内存(ThirdParty.Initialise(strInit)),然后每次调用ProcessInformation都会返回给定XML字符串的计算结果。
到目前为止,无论我将ServiceBehavior设置为什么,所有调用似乎都只使用一个线程,无论我使用多少单独的消费者,都可以帮助吗?
代码概述:
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.PerCall, UseSynchronizationContext = false)]
public class TestWCFService : ITestWCFService
{
private static ThirdPartyLib.ThirdPartyComClass ThirdParty;
private static bool initCalled = false;
private static int cntInit = 0;
private static int cntTrans = 0;
public TestWCFService()
{
if (ThirdParty == null)
{
ThirdParty = new ThirdPartyLib.ThirdPartyComClass();
}
}
public bool InitialiseThirdParty(string strInit, out string strError)
{
try
{
if (!initCalled)
{
cntInit++;
ThirdParty.Initialise(strInit);
initCalled = true;
}
strError = "Call Num " + cntInit;
return true;
}
catch (Exception ex)
{
strError = "ThirdParty.Initialise exception " + ex.Message + " 0n call number " + cntInit;
return false;
}
}
public bool ProcessInformation(string strRequestXML, int quoteMarker, out string strResponseXML, out string strError, out int quoteMarkerReturned)
{
try
{
cntTrans++;
quoteMarkerReturned = quoteMarker;
ThirdParty.ProcessInformation(strRequestXML, out strResponseXML);
strError = "Call Trans Num " + cntTrans;
return true;
}
catch (Exception ex)
{
strError = ex.Message + " On call trans num " + cntTrans;
strResponseXML = "Error";
quoteMarkerReturned = quoteMarker;
return false;
}
}
}
配置:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<compilation debug="true" />
</system.web>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="TestServiceBinding" bypassProxyOnLocal="true"
useDefaultWebProxy="false">
<readerQuotas maxDepth="524288" maxStringContentLength="524288"
maxArrayLength="524288" maxBytesPerRead="524288" maxNameTableCharCount="524288" />
<reliableSession inactivityTimeout="00:30:00" enabled="true" />
</binding>
</wsHttpBinding>
<mexHttpBinding>
<binding name="MEXTestServiceBinding" openTimeout="00:02:00"
sendTimeout="00:02:00" />
</mexHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="TestWcfServiceLibrary.TestWCFServiceBehavior"
name="TestWcfServiceLibrary.TestWCFService">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="TestServiceBinding"
name="" contract="TestWcfServiceLibrary.ITestWCFService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" bindingConfiguration="MEXTestServiceBinding"
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8731/Design_Time_Addresses/TestWcfServiceLibrary/TestWCFService/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="TestWcfServiceLibrary.TestWCFServiceBehavior">
<serviceMetadata httpGetEnabled="True"/>
<serviceThrottling maxConcurrentCalls="100" maxConcurrentSessions="100" maxConcurrentInstances="100"/>
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
答案 0 :(得分:2)
您的第三方COM组件似乎很可能是公寓线程,因此具有线程关联性。如果是这样,将只有一个线程在COM组件中完成工作。
然而,服务实现正在使用许多.NET线程,它们都必须排队使用特定的STA线程,这是唯一一个能够调用COM对象的线程。
答案 1 :(得分:1)
每个Microsoft文档:
并发的使用与实例化模式有关。在PerCall 实例化,并发性是不相关的,因为每个消息都是 由新服务实例处理。
// Multiple allows concurrent processing of multiple messages by a service instance.
// The service implementation should be thread-safe. This can be used to increase throughput.
[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
// Uses Thread.Sleep to vary the execution time of each operation.
public class CalculatorService : ICalculatorConcurrency
{
int operationCount;
public double Add(double n1, double n2)
{
operationCount++;
System.Threading.Thread.Sleep(180);
return n1 + n2;
}
public double Subtract(double n1, double n2)
{
operationCount++;
System.Threading.Thread.Sleep(100);
return n1 - n2;
}
public double Multiply(double n1, double n2)
{
operationCount++;
System.Threading.Thread.Sleep(150);
return n1 * n2;
}
public double Divide(double n1, double n2)
{
operationCount++;
System.Threading.Thread.Sleep(120);
return n1 / n2;
}
public string GetConcurrencyMode()
{
// Return the ConcurrencyMode of the service.
ServiceHost host = (ServiceHost)OperationContext.Current.Host;
ServiceBehaviorAttribute behavior = host.Description.Behaviors.Find<ServiceBehaviorAttribute>();
return behavior.ConcurrencyMode.ToString();
}
public int GetOperationCount()
{
// Return the number of operations.
return operationCount;
}
}
示例输出:( []中的数字表示线程ID)
2012-07-31 09:07:28,509 [9] DEBUG Microsoft.ServiceModel.Samples.CalculatorService - Leaving: Microsoft.ServiceModel.Samples.CalculatorService.Multiply(double, double) : 752.919376325402
2012-07-31 09:07:28,512 [17] DEBUG Microsoft.ServiceModel.Samples.CalculatorService - Leaving: Microsoft.ServiceModel.Samples.CalculatorService.Multiply(double, double) : 752.919376325402
2012-07-31 09:07:28,524 [13] DEBUG Microsoft.ServiceModel.Samples.CalculatorService - Leaving: Microsoft.ServiceModel.Samples.CalculatorService.Multiply(double, double) : 2143.10173334651
2012-07-31 09:07:28,524 [11] DEBUG Microsoft.ServiceModel.Samples.CalculatorService - Entering: Microsoft.ServiceModel.Samples.CalculatorService.Multiply(double n1 = 15.5665354410031, double n2 = 48.3678194919451)
2012-07-31 09:07:28,532 [22] DEBUG Microsoft.ServiceModel.Samples.CalculatorService - Entering: Microsoft.ServiceModel.Samples.CalculatorService.Multiply(double n1 = 94.7194438868758, double n2 = 29.8120223590229)
2012-07-31 09:07:28,534 [9] DEBUG Microsoft.ServiceModel.Samples.CalculatorService - Entering: Microsoft.ServiceModel.Samples.CalculatorService.Multiply(double n1 = 99.2045067247024, double n2 = 88.4957458770349)
2012-07-31 09:07:28,539 [4] DEBUG Microsoft.ServiceModel.Samples.CalculatorService - Entering: Microsoft.ServiceModel.Samples.CalculatorService.Multiply(double n1 = 99.2045067247024, double n2 = 88.4957458770349)
2012-07-31 09:07:28,539 [7] DEBUG Microsoft.ServiceModel.Samples.CalculatorService - Entering: Microsoft.ServiceModel.Samples.CalculatorService.Multiply(double n1 = 37.991849630136, double n2 = 41.7864370820049)
2012-07-31 09:07:28,539 [17] DEBUG Microsoft.ServiceModel.Samples.CalculatorService - Entering: Microsoft.ServiceModel.Samples.CalculatorService.Multiply(double n1 = 11.331077670367, double n2 = 55.5888338273339)
2012-07-31 09:07:28,539 [11] DEBUG Microsoft.ServiceModel.Samples.CalculatorService - Leaving: Microsoft.ServiceModel.Samples.CalculatorService.Multiply(double, double) : 752.919376325402
2012-07-31 09:07:28,539 [22] DEBUG Microsoft.ServiceModel.Samples.CalculatorService - Leaving: Microsoft.ServiceModel.Samples.CalculatorService.Multiply(double, double) : 2823.77817898976
2012-07-31 09:07:28,539 [17] DEBUG Microsoft.ServiceModel.Samples.CalculatorService - Leaving: Microsoft.ServiceModel.Samples.CalculatorService.Multiply(double, double) : 629.881393702645
2012-07-31 09:07:28,542 [9] DEBUG Microsoft.ServiceModel.Samples.CalculatorService - Leaving: Microsoft.ServiceModel.Samples.CalculatorService.Multiply(double, double) : 8779.17681696586
2012-07-31 09:07:28,544 [4] DEBUG Microsoft.ServiceModel.Samples.CalculatorService - Leaving: Microsoft.ServiceModel.Samples.CalculatorService.Multiply(double, double) : 8779.17681696586
2012-07-31 09:07:28,544 [7] DEBUG Microsoft.ServiceModel.Samples.CalculatorService - Leaving: Microsoft.ServiceModel.Samples.CalculatorService.Multiply(double, double) : 1587.54403419867
答案 2 :(得分:0)
问题是第三方DLL只是一个单线程的COM模型。我一直认为它是多线程的,但通过运行替换功能,它现在100%是第三方问题。非常感谢所有人的快速回复。看起来可能需要一些花哨的步法来使用一些额外的核心。我已经给该公司发了一封电子邮件,看他们是否有MT版本,但我对此表示怀疑。再次感谢。