我有一個與外部庫進行通信的控制檯應用程序。不幸的是,所有對庫的調用都必須使用相同的線程。在特定線程中運行代碼
如何將方法調用從一個線程發送到另一個線程? (而且,很明顯,發送方法的結果返回給調用線程。)
(不,這不是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