繁体   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