gpt4 book ai didi

wcf - WCF 服务中的线程

转载 作者:行者123 更新时间:2023-12-01 14:00:07 25 4
gpt4 key购买 nike

有一段代码:

class WCFConsoleHostApp : IBank
{
private static int _instanceCounter;

public WCFConsoleHostApp ()
{
Interlocked.Increment(ref _instanceCounter);
Console.WriteLine(string.Format("{0:T} Instance nr " + _instanceCounter + " created", DateTime.Now));
}
private static int amount;

static void Main(string[] args)
{
ServiceHost host = new ServiceHost(typeof(WCFConsoleHostApp));
host.Open();
Console.WriteLine("Host is running...");
Console.ReadLine();
}

#region IBank Members

BankOperationResult IBank.Put(int amount)
{
Console.WriteLine(string.Format("{0:00} {1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread) + " Putting...");
WCFConsoleHostApp.amount += amount;
Thread.Sleep(20000);
Console.WriteLine(string.Format("{0:00} {1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread) + " Putting done");
return new BankOperationResult { CurrentAmount = WCFConsoleHostApp.amount, Success = true };
}

BankOperationResult IBank.Withdraw(int amount)
{
Console.WriteLine(string.Format("{0:00} {1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread) + " Withdrawing...");
WCFConsoleHostApp.amount -= amount;
Thread.Sleep(20000);
Console.WriteLine(string.Format("{0:00} {1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread) + " Withdrawing done");
return new BankOperationResult { CurrentAmount = WCFConsoleHostApp.amount, Success = true };
}

#endregion
}

我的测试客户端应用程序在 50 个线程中调用该服务(服务是 PerCall)。我发现非常令人不安的是,当我添加 Thread.Sleep(20000) WCF 每秒创建一个服务实例时,使用来自池的不同线程。

当我删除 Thread.Sleep(20000) 时,会立即实例化 50 个实例,并使用大约 2-4 个线程来执行此操作 - 实际上我认为这是正常的。

有人能解释一下为什么 Thread.Sleep 在创建实例时会导致那些有趣的延迟吗?

最佳答案

您将您的实际服务实现(IBank 接口(interface)的实现)和您的服务宿主混合在同一个类中。

这绝对不是好的做法。

默认情况下,WCF 将通过设计为每个传入的请求实例化服务实现类的一个新的单独副本。这使得编写服务变得更加容易(无需为多线程而烦恼 - 每个请求都有自己的类) .

但是:您不应该将其与 ServiceHost 混合使用,因为您实际上只需要一个服务主机实例来托管可以处理成百上千个请求的服务类。

所以 - 创建一个类

class BankImplementation : IBank
{
private static int _instanceCounter;

BankOperationResult IBank.Put(int amount)
{
Console.WriteLine(string.Format("{0:00} {1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread) + " Putting...");
//WCFConsoleHostApp.amount += amount;
Thread.Sleep(20000);
Console.WriteLine(string.Format("{0:00} {1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread) + " Putting done");
return new BankOperationResult { CurrentAmount = WCFConsoleHostApp.amount, Success = true };
}

BankOperationResult IBank.Withdraw(int amount)
{
Console.WriteLine(string.Format("{0:00} {1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread) + " Withdrawing...");
//WCFConsoleHostApp.amount -= amount;
Thread.Sleep(20000);
Console.WriteLine(string.Format("{0:00} {1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread) + " Withdrawing done");
return new BankOperationResult { CurrentAmount = WCFConsoleHostApp.amount, Success = true };
}
}

用于您的服务代码,然后是一个单独的代码(甚至可能在一个单独的项目中)用于托管您的服务代码:

class WCFConsoleHostApp
{

public WCFConsoleHostApp ()
{
Interlocked.Increment(ref _instanceCounter);
Console.WriteLine(string.Format("{0:T} Instance nr " + _instanceCounter + " created", DateTime.Now));
}

static void Main(string[] args)
{
ServiceHost host = new ServiceHost(typeof(BankImplementation));
host.Open();
Console.WriteLine("Host is running...");
Console.ReadLine();

host.Close();
}
}

现在您获得了 WCFConsoleHostApp一个实例,它将在 host.Open() 启动 WCF 运行时并处理请求根据需要实例化尽可能多的 BankImplementation 类实例。

更新:好吧,WCF 服务也被“限制”了,例如您可以调整有多少个并发调用和实例。默认情况下,您会获得 10 个并发 session 和 16 个并发调用。如果您的服务已经在处理 16 个并发调用并且这些调用休眠了一段时间,则不会创建和处理额外的服务实例。

看到这个优秀blog post by Kenny Wolf有关服务节流的详细信息。您可以根据需要调整这些最大值。

关于wcf - WCF 服务中的线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1836402/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com