我有一个与外部库进行通信的控制台应用程序。不幸的是,所有对库的调用都必须使用相同的线程。在特定线程中运行代码
如何将方法调用从一个线程发送到另一个线程? (而且,很明显,发送方法的结果返回给调用线程。)
(不,这不是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);
}
}
}
}
搞清楚如何创建一个线程安全的队列确实是我遇到的问题,一旦你有了这个问题,这只是一个排队lambda函数的问题,代表你想完成的工作 – MathematicalOrchid
@MathematicalOrchid我编了一个代码示例。 – Gusdor
在静态构造函数创建一个线程,并保持它活着的等待。所有的作业(调用公共类的方法)都是“排队”,然后这个线程会逐个完成它们,然后再等待。 – Sinatr
你如何期望另一个线程接收“通知”?我想,它一定是在听他们到达 - 手动检查一些入站队列。你已经提到过,这不像GUI编程,所以你只是没有一些胜利形式,它会调用你的回调,所以你不能应用IncomingFunctionCall_OnArrived之类的东西 - 你仍然应该检查你的通知拥有。 – Agat
你的库绑定到你初始化它的线程(类似于一个UI),还是只需要序列化访问? – Gusdor