我有一个与外部库对话的控制台应用程序。不幸的是,对库的所有调用都必须从同一个线程进行。
如何将方法调用从一个线程发送到另一个线程?(并且,显然,将方法结果发送回调用线程。)
(不,这与 GUI 编程无关。不,使用 GUI 消息泵不起作用。)
我真正想要的是特定类上的每个方法始终在同一个线程中执行。但我不知道该怎么做。
我有一个与外部库对话的控制台应用程序。不幸的是,对库的所有调用都必须从同一个线程进行。
如何将方法调用从一个线程发送到另一个线程?(并且,显然,将方法结果发送回调用线程。)
(不,这与 GUI 编程无关。不,使用 GUI 消息泵不起作用。)
我真正想要的是特定类上的每个方法始终在同一个线程中执行。但我不知道该怎么做。
我的建议是按照 Windows 窗体和 WPF 的做法来设置它们的单线程消息泵 - 继承SynchronizationContext
。http://msdn.microsoft.com/en-us/library/system.threading.synchronizationcontext%28v=vs.110%29.aspx
在您的实现中,您需要维护一个线程安全的消息队列,类似于这个: http: //www.codeproject.com/Articles/56369/Thread-safe-priority-queue-in-C 您的消息泵工作线程将不断检查新的代表,并调用它们。
那么为什么不写一个消息泵呢?
好吧,通过继承SynchronizationContext
,您可以免费获得所有的 CLR 好东西BackgroundWorker
,AsyncOperationManager
以及新的await/async
模式关键字!他们都会神奇地加入你的图书馆线程。
这是基本消息泵的一些代码。它没有实现SynchronizationContext
:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace MessagePump
{
class Program
{
static void Main(string[] args)
{
MessagePump p = new MessagePump();
p.Start();
p.AddMessage(() => Console.WriteLine("message 1"));
p.AddMessage(() => Console.WriteLine("message 2"));
p.AddMessage(() => Console.WriteLine("message 3"));
Console.ReadLine();
p.Stop();
}
}
class MessagePump
{
bool m_Working = false;
Queue<Action> m_Actions = new Queue<Action>();
public void Start()
{
m_Working = true;
Thread t = new Thread(DoPump);
t.Name = "Message Pump Thread";
t.Start();
}
void DoPump()
{
while (m_Working)
{
try
{
Monitor.Enter(m_Actions);
while (m_Actions.Count > 0)
{
m_Actions.Dequeue()(); //dequeue and invoke a delegate
}
}
finally
{
Monitor.Exit(m_Actions);
}
Thread.Sleep(100); //dont want to lock this core!
}
}
public void Stop()
{
m_Working = false;
}
public void AddMessage(Action act)
{
lock (m_Actions)
{
m_Actions.Enqueue(act);
}
}
}
}