[英]Silverlight: Moving service calls and file processing to background thread
ProcessFile()
是在UIThread上運行還是在單獨的線程上運行。 如果它在UIThread上,如何將文件請求和ProcessFile()移動到單獨的Thread
?
var xClient = new ServiceReference1.Service1SoapClient();
xClient.Retrieve_File_Completed += new EventHandler<ServiceReference1.Retrieve_File_CompletedCompletedEventArgs>(xClient_Retrieve_File_Completed);
.
.//called on Page load
foreach(fileName in fileNames)
{
xClient.Retrieve_FileAsync(fileName);
}
.
.
void xClient_Retrieve_File_Completed(object sender, ServiceReference1.Retrieve_File_CompletedCompletedEventArgs e)
{
//Processing
ProcessFile(e.Result[0]); //Is this on UI Thread?
}
編輯:從答案,很明顯ProcessFile()
在UI線程上運行。 如何將文件請求和處理( ProcessFile()
)移動到單獨的Thread。 ProcessFile
只填充一些數據結構,在收到所有文件后使用這些數據結構更改UI。
使用“添加服務引用”功能時,Visual Studio自動生成的服務代理將自動在啟動服務調用的線程上分派已完成的回調事件。
在您的情況下,這意味着xClient_Retrieve_File_Completed
確實在您的UI線程上執行。
更新:實際上很難將文件請求和文件處理全部放在一個線程上,然后在所有請求和處理完成后更新UI,因為您必須保持線程處於活動狀態,同時對服務的請求全部完成。 無法保證服務請求將按照發送順序完成,因此您必須跟蹤已完成請求的數量,並且只有在所有請求完成后,您才能通知UI並結束線程。
對我來說,這聽起來像一個脆弱而復雜的設計,不幸的是,Silverlight中不存在您可能用於此類設計的CountDownEvent
。
或者,您可以考慮更改服務和ProcessFile
的設計,以便您可以同時請求和處理所有文件,這樣您只需要發出一個服務請求(除非您通過網絡向和從數據庫發送大量數據)服務)。 然后你可以在一個鏡頭中生成一個BackgroundWorker
( 由Matthew Paul Keelan在他的回答中建議 )來處理所有文件。 您的代碼看起來與此類似:
// Called on Page load.
// Note that there is only one service call with all file names as parameter.
xClient.Retrieve_FileAsync(fileNames);
// ...
// Elsewhere in the class
BackgroundWorker _worker;
void xClient_Retrieve_File_Completed(object sender, ServiceReference1.Retrieve_File_CompletedCompletedEventArgs e)
{
_worker = new BackgroundWorker()
_worker.DoWork += (sender, args) =>
{
// Only one call to ProcessFile.
ProcessFile(e.Result);
};
_worker.RunWorkerCompleted += (sender, args) =>
{
// Update UI here
};
_worker.RunWorkerAsync();
}
您可以使用Dispatcher.CheckAccess()方法確定代碼是否在UI線程上執行:
如果ProcessFile方法是一項昂貴的操作,您可以嘗試將其卸載到BackgroundWorker。 Pete Brown在這里有一個很好的描述如何做到這一點:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.