從體系結構的角度來看:
消息隊列將應用程序的位分開。您可以在Windows窗體應用程序中依賴Windows爲您創建和管理的Message Queue。 Google for PostMessage/GetMessage等。這通常稱爲「消息傳遞」。
典型Arcitecture您的應用程序的
- 一部分「推」的請求進入隊列
- 您的應用程序的其它部分從隊列中「拉」的請求和結果寫入第二個隊列。
- 第一部分可以從第二個「結果」隊列「拉」請求並顯示給用戶。
所以它看起來像這樣:
應用程序 - >請求的隊列 - >處理引擎 - >結果隊列 - >應用
處理引擎可以在同一應用程序,在同一個線程或不同的線程/進程(甚至不同的機器)上。
您可以使用簡單的隊列:說一個Queue<string>()
(只要您使用鎖來訪問它)或增加複雜性或更多更復雜/功能的隊列。
問題與天真策略和其他解決方案...事情要考慮:
- ,如果你做一個新的請求,而舊的還未完成,會發生什麼?
- 如果發生錯誤會怎麼樣?你想內聯錯誤嗎?你可以使用另一個隊列的錯誤?
- 你想重試嗎?
- 如果信息丟失會發生什麼? (即請求被推送,但沒有響應進入...)?有事務性隊列等
示例代碼
object oLock = new object();
Queue<string> requests = new Queue<string>();
Queue<string> responses = new Queue<string>();
Thread mThread;
AutoResetEvent mEvent = new AutoResetEvent(false);
public Form1()
{
InitializeComponent();
mThread = new Thread(ProcessingEngine);
mThread.IsBackground = true;
mThread.Start();
}
private void ProcessingEngine()
{
string result;
string request = null;
while (true)
{
try
{
mEvent.WaitOne();
lock (oLock)
{
request = requests.Dequeue();
}
var wc = new WebClient();
result = wc.DownloadString(request);
lock (oLock)
{
responses.Enqueue(result);
}
}
catch (Exception ex)
{
lock (oLock)
{
responses.Enqueue(ex.ToString());
}
}
}
}
private void timer1_Tick(object sender, EventArgs e)
{
lock (oLock)
{
//Stick in a new request
requests.Enqueue("http://yahoo.com");
//Allow thread to start work
mEvent.Set();
//Check if a response has arrived
if (responses.Any())
{
var result = responses.Dequeue();
listBox1.Items.Add(result.Substring(1,200));
}
}
}
}
-1。這破壞了可伸縮性,如果線程例子超時 - UI會阻塞,直到超時發生,這是不好的。使用Threading.Timer允許在單獨的線程上執行,然後調用回主線程(窗口上的Invoke方法),僅用於UI更新。 – TomTom
怎麼回事?我還沒有看到RunWorkerAsync在任何時候都會阻塞的情況,你不能直接從Threading.Timer.Tick中更新UI,並且在Timer中使用'Invoke'''會得到與'RunWorkerCompleted'更新結果完全相同的結果。 DoWork'在它自己的線程中執行,所以請解釋你爲什麼認爲UI會阻塞。 – MagnatLU
Comp投票,這樣做沒有錯。不會發生阻塞,試圖運行繁忙的BGW會產生異常。用任何一種計時器。至少它放鬆了OP對擁有太多線程的擔憂。 –