[英]Windows 8 Thread improvements - alternative to Task.Run()?
我繼承了C#/ XAML / Win 8應用程序。 有一些代碼設置為每n秒運行一次。
設置的代碼是:
if(!_syncThreadStarted)
{
await Task.Run(() => SyncToDatabase());
_syncThreadStarted = true;
}
上面的代碼只運行了一次。
然后在SyncToDatabase()中,我們有:
while (true)
{
DatabaseSyncer dbSyncer = new DatabaseSyncer();
await dbSyncer.DeserializeAndUpdate();
await Task.Delay(10); // after elapsed time re-run above code
}
DeserializeAndUpdate方法查詢內存中的對象集合並將這些對象推送到Web服務。
有時,向Web服務發送請求所花費的時間比預期的長,這意味着發送重復項。
問題:有沒有辦法讓線程或某種類型的線程池/后台工作程序在SyncToDatabase()方法中停止/中止/銷毀,然后在完成后初始化/啟動它? 這樣可以確保在先前的請求仍處於待處理狀態時,不會觸發任何后續請求。
編輯:關於線程,我不是很了解,但是我想要的邏輯是:
創建一個每x秒運行某種方法的線程,並在啟動該線程時停止“每x秒運行”部分,在線程完成后再次啟動“每x秒運行”部分。
例如,如果線程在10:01:30 AM開始,並且直到10:01:39 AM(9秒)才完成,則下一個線程應在10:01:44 AM(工作完成5秒后)開始-這有意義嗎? 我不希望同時運行2個或更多線程。
這是我上面的代碼:
var period = TimeSpan.FromSeconds(5);
var completed = true;
ThreadPoolTimer syncTimer = ThreadPoolTimer.CreatePeriodicTimer(async (source) =>
{
// stop further threads from starting (in case this work takes longer than var period)
syncTimer.Cancel();
DatabaseSyncer dbSyncer = new DatabaseSyncer();
await dbSyncer.DeserializeAndUpdate(); // makes webservices calls
Dispatcher.RunAsync(CoreDispatcerPriority.High, async () =>
{
// Update UI
}
completed = true;
}, period,
(source) =>
{
if(!completed)
{
syncTimer.Cancel(); // not sure if this is correct...
}
}
謝謝,安德魯
這不是Windows 8特有的。通常Task.Run
用於CPU綁定工作,將其卸載到池線程並保持UI(或核心服務循環)響應。 就您而言,據我所知,主要負載是dbSyncer.DeserializeAndUpdate
,它已經是異步的,並且很可能是受網絡IO約束的,而不是受CPU約束的。
此外,原始代碼的作者在await Task.Run(() => SyncToDatabase())
之后執行_syncThreadStarted = true
。 這沒有任何意義,因為多虧了await
,到執行_syncThreadStarted = true
時,池線程上的工作已經完成了。
要取消SyncToDatabase
內部的循環,可以使用“ 任務取消模式” 。 SyncToDatabase
本身是async
方法嗎? 我猜是這樣,因為while loop
有一個await
。 鑒於此,調用它的代碼可能看起來像這樣:
if(_syncTask != null && !_syncTask.IsCompleted)
{
_ct.Cancel();
// here you may want to make sure that the pending task has been fully shut down,
// keeping possible re-entrancy in mind
// See: https://stackoverflow.com/questions/18999827/a-pattern-for-self-cancelling-and-restarting-task
_syncTask = null;
}
_ct = new CancellationTokenSource();
// _syncTask = SyncToDatabase(ct.Token); // do not await
// edited to run on another thread, as requested by the OP
var _syncTask = Task.Run(async () => await SyncToDatabase(ct.Token), ct.Token);
_syncThreadStarted = true;
SyncToDatabase
可能類似於:
async Task SyncToDatabase(CancellationToken token)
{
while (true)
{
token.ThrowIfCancellationRequested();
DatabaseSyncer dbSyncer = new DatabaseSyncer();
await dbSyncer.DeserializeAndUpdate();
await Task.Delay(10, token); // after elapsed time re-run above code
}
}
檢查此答案以獲取有關如何取消和重新啟動任務的更多詳細信息。
我可能誤解了這個問題,但是在繼續執行之前, SynchToDatabase()
的執行將在await dbSyncer.DeserializeAndUpdaet()
的完成之前await dbSyncer.DeserializeAndUpdaet()
(由於await
關鍵字,請await dbSyncer.DeserializeAndUpdaet()
數字;)),然后再執行繼續操作,這將延遲10毫秒(您需要10毫秒還是10秒鍾? Task.Delay
參數以毫秒為單位),然后循環返回以重新執行DbSyncer
方法,所以我看不到問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.