簡體   English   中英

Windows 8線程改進-Task.Run()的替代方法?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM