为什么我总是在使用wcf托管另一个线程时更改线程ID?

时间:2011-09-17 09:07:42

标签: c# multithreading wcf

在我的应用程序中,我托管 WCF服务:

private void StartService()
{
    m_serviceHost = new ServiceHost(typeof(...));
    m_serviceHost.Open();
}

private void button1_Click(object sender, EventArgs e)
{                        
    Thread t = new Thread(StartService);
    t.IsBackground = true;
    t.Start();
    // ...
}

服务本身只有一种方法:

public void SendMessage(string message)
{
    MessageBox.Show(String.Format("Message '{0}' received on thread {1} : MessageLoop = 
        {2}", message, Thread.CurrentThread.GetHashCode(), Application.MessageLoop), 
        "MessagingService.SendMessage()");
}

当客户端调用此操作时,我得到以下响应:

Message 'hello client : message 9 recieved on thread **12**
Message 'hello client : message 9 recieved on thread **15**
Message 'hello client : message 9 recieved on thread **17**
...

为什么线程ID总是会改变?当我创建ServiceHost时,我只把他放在另一个线程上! 我不是每次都把他放在另一个主题上...只有一次

如何将主机放在另一个线程中(就像我做的那样)并且只获得单个后台线程ID?

2 个答案:

答案 0 :(得分:2)

在另一个线程上启动服务,但ServiceHost本身使用多个线程来处理请求。

如果您的服务不是线程安全的,您可以通过使用ServiceBehaviorAttribute修改服务类并将ConcurrencyMode设置为Single来强制以单线程方式执行它:< / p>

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single)]
public class ServiceClass
{
}

答案 1 :(得分:1)

IIRC正确地说ConcurrencyMode.Single并不保证使用单个线程...它保证只有一个线程可以访问服务实例...从而防止了两个(或更多)线程可能产生的并发问题使用相同的服务实例(状态可能会被破坏)。

我想你想强制执行一个线程来处理所有调用,所以一切都按顺序完成,没有任何状态被破坏。但是使用默认的InstanceContextMode(PerCall),每个调用都会获得自己的服务实例。并且将ConcurrencyMode设置为single,您确定只有一个线程访问服务实例。

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single, 
    InstanceContextMode = InstanceContextMode.PerCall)]
public class MessageService : IMessageService
{
    public string ReturnMessage()
    {
        return String.Format("Thread {0}", Thread.CurrentThread.ManagedThreadId);
    }
}