我正在使用 NetCoreServer 連接到 XMPP 聊天服務器。一切都按預期作業。每當服務器發送訊息時,我都會使用普通方法對其進行處理processData(string data)。問題是,如果該方法花費的時間超過特定時間,服務器將關閉連接。
我正在考慮異步執行該方法,但問題是來自服務器的訊息可以分成幾部分。方法 process data 檢測到,如果收到的訊息只是整個訊息的一部分,它將存盤它。下次呼叫它時,將新訊息附加到舊訊息,檢查新訊息是否完成它,或者它是否需要等待下一條訊息,依此類推,直到它有一個完整的訊息。然后它會繼續處理它,所以如果它被異步呼叫,呼叫必須在執行之前等待以前的呼叫,而不會阻塞 NetCoreServer 的 OnReceive。
每當來自服務器的新資料到達時,我正在考慮將 a 添加var task=new Task(() => { ProcessData(result); });到佇列中,但我不知道如何鏈接它們的執行或如何繼續。或者我可以在資料到達時將資料存盤在佇列中,并且ProcessData每當有新訊息添加到佇列中時以某種方式觸發一個事件來呼叫。但是除了不知道如何之外,我遇到了同樣的問題,觸發的事件應該等待前一個事件的完成。
ProcessData 看起來像這樣:
public Class DataProcessor
{
private string Buffer;
public void processData(string data)
{
if(PartialData(data)) {
Buffer =data;
return;
}
else //continue processing
}
uj5u.com熱心網友回復:
您可以使用許多工具來解決此問題。在這里,我將展示一個TPL 資料流解決方案。您將需要兩個ActionBlock<T>s,一個用于連接訊息的拆分部分,一個用于處理完整的消??息。我以相反的順序將它們寫在下面,因為第一個塊在構建程序中需要了解第二個塊。此示例假定每條完整訊息的最后一部分以點字符結尾:
var block2 = new ActionBlock<string[]>(parts =>
{
string completeMessage = String.Join(" ", parts);
Console.WriteLine($"Processing message: {completeMessage}");
});
var parts = new List<string>();
var block1 = new ActionBlock<string>(rawMessage =>
{
if (rawMessage is null) { block2.Complete(); return; }
parts.Add(rawMessage);
if (rawMessage.EndsWith("."))
{
block2.Post(parts.ToArray());
parts.Clear();
}
});
block1.Post("Hello");
block1.Post("world.");
block1.Post("The quick");
block1.Post("brown fox.");
block1.Post(null); // Signal that there are no more messages
block1.Complete();
await block2.Completion;
Console.WriteLine("Processing terminated");
輸出:
Processing message: Hello world.
Processing message: The quick brown fox.
Processing terminated
(現場演示)
如您所見,有一個List<string>包含當前收到的不完整訊息的部分。每次訊息完成時,部件都會傳播到block2,并且串列會被清除。
帶有 value 的特殊訊息null表示將不再接收訊息,因此您可以Complete使用block2and awaitfor itsCompletion來干凈而優雅地終止行程。
兩個ActionBlock<T>s 相互并行作業。它們中的每一個都包含自己的內部輸入佇列,其中包含要處理的訊息(該佇列是無界的)。該Post方法只是將訊息發送到目標塊的輸入佇列,無需等待訊息的處理。true如果訊息被目標塊接受,則此方法回傳,false否則回傳。不接受訊息的常見原因是Complete方法已被呼叫,或者由于發生了未處理的例外而導致塊失敗。
The TPL Dataflow library is part of the standard libraries in .NET 6. You don't need to install anything to use it. Unless you are targeting the old .NET Framework, in which you need to install this NuGet package.
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/437399.html
