从bakcground线程调用UI线程上的许多方法

时间:2018-10-16 10:43:00

标签: c# multithreading thread-safety

有关我的问题的一些信息:

我有一个Windows Forms应用程序,该应用程序具有可以并行计算很长时间的多线程。在计算这些线程时,修改UI元素(例如,标签,文本框,按钮等)并写入RichTextBox。 我有很多委托来进行线程安全调用和检查InvokeRequired很多次。

我有很多这样的方法:

private void AppendText(string text)
{
    if(richTextBox.InvokeRequired)
    {
        Invoke(myDelegate, new object[] { text });
    }
    else
    {
        richTextBox.Append(text);
    }
}

我的问题是:

这是从后台线程修改UI线程上的控件的一种好方法,还是我犯了一些体系结构错误?

1 个答案:

答案 0 :(得分:1)

以下是一个简单的代码,用于说明let { compose, mapObjIndexed } = require('ramda') const inc = (n: number) => n + 1 const inc2 = (n: number, count = 2) => n + count const g = { inc, inc2, } const inc3 = (n: number) => n + 3 const g2: any = Object.keys(g).reduce( (previousValue, key) => { console.log('props', previousValue, key) return { ...previousValue, [key]: (...arg: any[]) => { return inc3(g[key](...arg)) }, } }, {}) // const g2 = mapObjIndexed((action: any) => compose(inc3, action))(g) // => So you can use // But in this case g2 is any, so I have to define type of g2. // How can I define type of g2(in this case any) depend on the g console.log('>>', g2.inc(2), g2.inc2(5)) // 6 and 10

的用法
Async-Await
  • public async Task Main() { var result = await Background("Test"); // Update Ui here, its on Ui thread } // Executed Asynchronously in the Background public async Task<string> Background(string text) { return await Task.FromResult(text); } 方法是异步处理的,如果它在网络上像db调用一样,则不需要线程池线程,如果在内存中,它将使用线程池线程
  • 一旦使用Background方法,结果就可以在控件上自动更新为Ui线程
  • 您甚至可以显式使用Background处理数据,然后更新结果
  • Task Parallel Library仍然是阻塞呼叫,尽管它将释放呼叫上下文,这意味着Ui不会冻结,仍然可以访问,但是可以使用await进行非阻塞呼叫,返回时可以用来更新Ui,尽管您始终必须阻止Main / Ui线程退出

编辑1(异步按钮单击事件)

Task.Run