Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/react-native/7.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# 在UI线程上运行的TPL数据流块_C#_Multithreading_User Interface_Dataflow_Tpl Dataflow - Fatal编程技术网

C# 在UI线程上运行的TPL数据流块

C# 在UI线程上运行的TPL数据流块,c#,multithreading,user-interface,dataflow,tpl-dataflow,C#,Multithreading,User Interface,Dataflow,Tpl Dataflow,我正在构建一个数据流管道来执行自然发生流中的各种处理(主要是I/O,但有些是CPU处理)。该流程目前处于以下基本模式: 从文件加载数据 使用转换块解析记录 通过REST将对象序列化并上载到服务器 此处理管道可以自动启动,也可以通过GUI启动。因为当它从GUI启动时,我希望向最终用户提供进度消息。如果我在第1步和第2步之间添加一个BufferBlock,在第3步之后添加一个ActionBlock,并将选项设置为在与UI相同的线程上运行,那么其他块是否仍会使用自己的线程池从UI上运行 我正在看这篇M

我正在构建一个数据流管道来执行自然发生流中的各种处理(主要是I/O,但有些是CPU处理)。该流程目前处于以下基本模式:

  • 从文件加载数据
  • 使用转换块解析记录
  • 通过REST将对象序列化并上载到服务器
  • 此处理管道可以自动启动,也可以通过GUI启动。因为当它从GUI启动时,我希望向最终用户提供进度消息。如果我在第1步和第2步之间添加一个
    BufferBlock
    ,在第3步之后添加一个
    ActionBlock
    ,并将选项设置为在与UI相同的线程上运行,那么其他块是否仍会使用自己的线程池从UI上运行

    我正在看这篇MSDN文章:但关于这种行为,我不是很清楚。我可以从管道中触发一个可以在UI线程上运行的事件来完成这个任务吗


    编辑:管道将从UI上的
    BackgroundWorker
    对象启动,而不是直接从UI线程启动。

    多亏了Noseratio的建议,我实际上重新设计了如何完成这项工作,并且能够让它毫无问题地工作。我删除了
    BackgroundWorker
    对象,因为它不是必需的。相反,我将整个数据流包装在一个异步方法中,该方法将各种
    Progress
    参数作为进度更新的回调。由于在先前存在的块中调用了
    progress
    Report()
    方法,因此没有使用额外的TPL块来发布进度。此外,由于这是一个异步函数,因此表示数据流的任务不是在UI线程上运行,而是在线程池线程上运行。主要的一点是,
    Progress
    对象的回调在创建它们的线程上运行,因为在构建过程中它们捕获了当前的同步上下文。以下是解决我的问题的示例:

    public static async Task ProcessData(IProgress<int> ReadProg, IProgress<int> UploadProg)
    {
          var loadBuffer = new BufferBlock<string>();
          var parseBlock = new TransformBlock<string, MyObject>(async s =>
          {
              if(await DoSomething(s))
                  ReadProg.Report(1);
              else
                  ReadProg.Report(-1);
           });
           ...
           //setup of other blocks
           //link blocks
           //feed data into pipeline by adding data into the head block: loadBuffer
           //await ALL continuation tasks of the blocks
    }
    
    public静态异步任务ProcessData(IProgress ReadProg、IProgress UploadProg)
    {
    var loadBuffer=new BufferBlock();
    var parseBlock=newtransformblock(异步s=>
    {
    如果(等待剂量测定)
    ReadProg.报告(1);
    其他的
    ReadProg.报告(-1);
    });
    ...
    //其他区块的设置
    //连接块
    //通过将数据添加到头块loadBuffer,将数据馈送到管道中
    //等待模块的所有继续任务
    }
    


    然后在UI中,我创建了
    Progress
    对象,并将它们传递到异步
    ProcessData
    方法中。无论何时在异步处理方法中调用
    Process.Report()
    方法,UI都会毫无问题地更新。

    是否使用
    DataflowBlockOptions.TaskScheduler
    使其在UI线程中运行?一段代码将有助于理解这更多的是一个理论问题。我还在计划这个功能。到目前为止,它还没有报告进展情况。使用
    DataflowBlockOptions.TaskScheduler
    是我告诉那些特定块在UI线程上运行的方式。我会使用
    Progress
    模式,而不是求助于UI线程TaskScheduler。我想这里不需要
    BackgroundWorker
    。只需在UI线程上创建
    Progress
    (它会捕获s.context并在内部使用
    sc.Post
    )。然后从您的数据流管道调用它,无论进展如何。谢谢您的建议。我会调查的。