不使用Task.Wait()的cancellationToken

3

我有一个长时间运行的任务和两个按钮的winforms应用程序

按下“开始”按钮会启动一个带有取消令牌的新任务。如果按下“停止”按钮,则会调用取消令牌的Cancel方法。

我希望在整个过程中UI可用,那么我在哪里放置try catch块?在我看到的所有示例中,它们都将其放置在t.Wait()周围。

但如果我这样做,UI就会被冻结,这也是我首先使用Task的原因,以便在执行任务时继续使用UI。那么,在不使用Task.Wait的情况下,该如何放置try catch块呢?

开始按钮:

 tokenSource2 = new CancellationTokenSource();
   ct = tokenSource2.Token;
   t = new Task(doStart, ct);
   t.Start();

停止按钮:

tokenSource2.Cancel();

如何取消不可取消的异步操作:http://blogs.msdn.com/b/pfxteam/archive/2012/10/05/how-do-i-cancel-non-cancelable-async-operations.aspx - Servy
1个回答

2

你可以更新 doStart 方法来处理取消事件并优雅地退出任务,这样你就不需要使用 Wait 方法了。例如:

public void doStart(CancellationToken token)
{
    while(...)
    {
        ...
        if (token.IsCancellationRequested)
            break;
    }
}

另外一种方法是等待另一个线程返回任务结果,例如:

Thread.QueueUserWorkItem((state) =>
{
    try
    {
        t.Wait();
    }
    catch(...)
    {
        ...
    }
});

请注意,在第二种情况下,您并没有停止任务,而是继续进行其他操作或忽略该任务,尽管它尚未完成。只要可能,第一种选择是更可取的。 - Servy
@Servy 我同意,但问题是如何不阻塞用户界面。 - James
不要"阻塞UI",只是什么也不做,而且不等待任何东西。 - Servy
@Servy 这段代码只是处理另一个线程上的结果的示例,我正在使用手机回答,所以很难编写完整的代码。OP可以更新或更改它以适应自己的需求。不过,我同意你最初的观点,第一种解决方案是最好的。 - James
第二个示例引入了第二个线程来观察第一个线程... 这不是正确的做法(-1)。应该使用Continuations(协程)来解决这个问题。 - usr
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接