Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何安排有条件的连续剧_C#_C# 4.0_Asynchronous_Task Parallel Library_Continuations - Fatal编程技术网

C# 如何安排有条件的连续剧

C# 如何安排有条件的连续剧,c#,c#-4.0,asynchronous,task-parallel-library,continuations,C#,C# 4.0,Asynchronous,Task Parallel Library,Continuations,我有一些关于LINQ查询的GUI。执行查询需要一些时间,因此我希望GUI能够响应并显示总线指示器和进度条。许多查询是为了检查数据中是否存在某些条件。如果查询返回空结果,应用程序将继续进行下一次查询。如果返回结果,返回集的严重性将为“警告”或“错误”。如果是警告,则应继续执行。如果是错误,则应停止 许多代码使用线程池和GUI玩“乒乓球”。准代码: TaskFactory.StartNew(()=> { Run in background }.ContinueIn

我有一些关于LINQ查询的GUI。执行查询需要一些时间,因此我希望GUI能够响应并显示总线指示器和进度条。许多查询是为了检查数据中是否存在某些条件。如果查询返回空结果,应用程序将继续进行下一次查询。如果返回结果,返回集的严重性将为“警告”或“错误”。如果是警告,则应继续执行。如果是错误,则应停止

许多代码使用线程池和GUI玩“乒乓球”。准代码:

TaskFactory.StartNew(()=>
    {
       Run in background
    }.ContinueInGui(()=>
    {
       Update something
    }).ContinueInBackground(()=>
    {
      Do more work;
    }).ContinueInGui(()=> etc etc
这是干净漂亮的。但是,如果在数据中发现错误,我看不出如何插入条件以转到不同的延续路径或断开延续链

ContinueWithIf(谓词,委托{},任务调度器)没有方法 我是否使用TaskCancellation,是否引发异常?或者有一些简单的分支机制,我没有想到?

< P>如果有错误,你应该考虑相应地做出任务错误。然后您可以在
连续调用中使用etc

在任务生命周期结束时,基本上有三种可能的状态:

  • RANTO补全
  • 取消
  • 错误的

您可以将
ContinueWith
应用于这些状态的任何合理组合,如果您想根据错误、成功和取消等执行不同的操作,您可以将不同的ContinueWith附加到同一父任务。

这里的一个好选项是使用
取消令牌源,如果你想“打破”你的延续链,就把它标记为取消。通过将后续任务包含在
ContinueWith
中,您可以通过将
取消令牌源
标记为已取消,使它们在任何时候都不会被安排

如果您真的想使用谓词,而不是在main方法中设置continuation,那么您需要创建一个自定义方法来处理这个问题。这可以通过一个扩展方法来实现,该扩展方法附加了一个continuation,该continuation可以检查谓词,并在适当的情况下触发continuation。这看起来像:

public static Task ContinueWithIf(this Task task, Func<bool> predicate, Action<Task> continuation, TaskScheduler scheduler)
{
    var tcs = new TaskCompletionSource<object>(); 

    task.ContinueWith( t =>
    {
        if (predicate())
        {
            new TaskFactory(scheduler).StartNew( 
                () => 
                {
                    continuation(task); 
                    tcs.SetResult(null); 
                });
        }
        else
        {
            tcs.TrySetCanceled();
        }
    });

    return tcs.Task;
}
公共静态任务ContinueWithIf(此任务、Func谓词、操作继续、任务调度程序)
{
var tcs=new TaskCompletionSource();
task.ContinueWith(t=>
{
if(谓词())
{
新建TaskFactory(调度程序)。开始新建(
() => 
{
继续(任务);
tcs.SetResult(空);
});
}
其他的
{
tcs.trysetconceled();
}
});
返回tcs.Task;
}

当然,您可能还想为
任务
创建一个版本,以及处理任务上的故障/取消状态。也就是说,它应该能正常工作。

它们本身不是应用程序错误。我的应用程序正常工作。该应用程序的目的是运行检查。它们可能返回“错误”/“警告”/“信息”类别(或空)的记录。如果它们属于错误类别,用户应在重新运行检查之前纠正这些问题。可以把它想象成一个编译器,它可以返回各种问题集,而不会导致崩溃。我将查看TaskContinuationOptions,但我觉得我在混搭苹果和橙子。如果不将数据流映射到任务执行错误代码,数据流就不能被数据驱动,那就很奇怪了。@Tormod:对,我明白你的意思。恐怕我不知道怎样把链条分开。您必须稍后调用
ContinueWith
,而不是在任务创建点设置链。显然,C#5中的async/await将使所有这些变得更容易…@JonSkeet:您应该能够使用CancelationTokenSource触发取消,并结合NotnCanceled/OnlyonCanced来“分割”链。这实际上是在接收到特定于应用程序的错误时“取消”基于谓词的延续。@ReedCopsey:是的,这样就可以了。它仍然有点难看——当然,它不能很容易地将其与真正的外部取消区分开来。@JonSkeet:True——尽管它有点取决于任务。我认为这是一种真正的取消——你实际上是在根据当前任务的结果取消未来的任务。谢谢。有点面向方面(-ish)。但至少它不会分支或中断执行。它将正确地使下一步主体的执行取决于谓词。但当链接在一起时,即使Task2上的条件失败,Task3仍将执行。因此,除非我重用一些复杂的谓词,否则好处是微乎其微的。你同意我的想法吗?@Tormod:我编辑以修复一个bug(并使其编译)-在当前情况下,Task2将显示为已取消,因此你的Task3可以仅使用
订阅RandoCompletion
,它将正常工作…哇哦+1仅适用于taskcompletionsource,我希望在今后的时间里能够更多地应用该类。这看起来很有趣。我仍然不确定我们是否找到了最好的方法将其打包到一个扩展方法中,从而得到一个干净的语法。最好还包装适当的continuationoptions。但一切似乎都是可以解决的。至少我看到了允许它发生的控制流。仔细考虑后,“取消”是一个合适的词。非常感谢你举了个例子。OP的问题和我的不一样,但你的例子对我帮助很大。谢谢。出于好奇,在谓词条件内启动新的
子任务的原因是什么?不能通过调用将所有相关参数(调度程序等)直接传递到外部
ContinueWith
吗?