避免过程中表格挂起的任务方法

Task method to avoid hanging of form during process

我有处理大数据的过程,并在过程结束时将结果显示到文本框。

问题是表单在几秒钟内变得不可移动,它不是 "not responding" 挂起状态或完全冻结,我可以在执行过程中使用按钮停止进程。但是我无法在桌面上移动表格几秒钟的处理时间。

我不需要在过程中显示结果,它显示在计算和 Environment.NewLine 作为完整列表。但我想以某种方式避免 GUI

的这种短时间固定状态

我试图在任务中找到使用 UI 操作更新文本框显示:

private void button1_Click(object sender, EventArgs e)
{
    Process(); 
    Display(); 
}

private void Display()
{
    Task.Factory.StartNew(() => {              
        Invoke((Action)(() =>
            {
                /// Textbox output
            }));
    });
}

现在我可以在此过程中移动表单,但是如果在表单上按下鼠标单击,它只会在我释放鼠标按钮之前不允许显示结果。我也不确定这种方法有多安全。我试图弄清楚哪种 Task 方法对这种情况更好、更有用。

Invoke 方法正在 UI 上下文中执行,任务正在后台 运行 执行。这样运行操作没有任何意义。

  1. 创建事件处理程序async
  2. 不要使用StartNew方法,改用Task.Run
  3. await那个任务
  4. 之后在 UI 上下文中调用 Display 方法

因此您的代码可能如下所示:

private async void button1_Click(object sender, EventArgs e)
{
    // run process in background
    await Task.Run(() => Process());
    // return to UI context
    Display(); 
}

private void Display()
{
    // Textbox output
}

尝试像这样使用 Task 对象:

Task myTask = new Task(new Action(()=>
{
// your operations code here
}));
myTask.ContinueWith(c=>
{
  yourControlName.BeginInvoke(new Action(()=>
 {
  // update control here
 }));
});
myTask.Start();

请注意,您还可以通过在 Task 之前创建它来在任务执行其工作时显示某种加载表单的对话框,将其放置在继续块中,并在任务之后显示对话框开始

Begininvoke 将向创建控件的线程发出信号,让其对 ui 进行更改,事情是

如果您不指定控件名称,它将以此处的表单为目标,并且它们在您的程序中共享相同的创建者线程,但在复杂的多线程应用程序中并不相同.

编辑 感谢 VMAtm 指出不推荐使用 Task 构造函数,我做了一些挖掘并发现了这个: msdn blog

话虽如此 在你的情况下正确的做法是:

Task.Factory.StartNew( ()=>
{
  //computing here


      yourControlName.BeginInvoke(new Action(()=>
     {
      // update control here
     }));
}));
   // or display() here if you dont have to do it using begininvoke

然而 因为 StartNew 根据 Stephen Cleary 是危险的(再次感谢 VMAtm ) 在你的情况下最好的方法是:

await Task.Run(() => Process());
Display();

请注意,所有这些都适用于您的情况,这只是理想情况下哪个适用于哪种情况的问题...