如何为简单的解析语句实现Dispatcher BeginInvoke?

时间:2016-03-28 02:52:37

标签: c# multithreading

我在C#应用程序中有一个后台线程和一个循环主线程。

在这个后台线程上,我必须从UI访问Text并将其解析为在条件语句中使用,如下所示:

        int i = 0;

        int loopNum = int.Parse(Loop_Number.Text); //< What I need to access

        if (loopNum > 0)
        {
            while (i < loopNum)
            {
                //DoStuff
            }
        }

上述语句的问题是在后台线程中运行而不是主UI线程。因此,程序会为该int.Parse语句抛出InvalidOperationException。

例外有这方面的信息:

附加信息:调用线程无法访问此对象,因为另一个线程拥有它。

因此,我只有一个UI线程并暂时运行此线程如何在此后台线程中访问Loop_Number.Text。

我尝试过以下代码:

        Dispatcher.BeginInvoke((Action)(() => { int loopNum = int.Parse(Loop_Number.Text); }));

但是然后loopNum脱离了条件语句的上下文。

1 个答案:

答案 0 :(得分:1)

简短的答案将解决眼前的问题,即您需要使用Invoke()代替BeginInvoke()

string text = (string)Dispatcher.Invoke(() => Loop_Number.Text);

int loopNum = int.Parse(text);

现在,那就是说,你的问题中有迹象表明你只是做错了。 :(


首先,您根本不需要直接访问UI对象。即从您报告的异常中,Loop_Number变量可能是对某些WPF控件的引用,如TextBox。相反,您应该遵循某种数据绑定模式,例如MVVM,其中您有一个非UI对象,该对象具有绑定到UI控件的属性,并且接收所需的数字。

这样做,不仅可以在UI线程中设置属性,允许在其他地方(例如在不同的线程中)访问该值而无需调用UI线程,可以使属性具有类型int和WPF将为您转换文本。您甚至根本不需要致电int.Parse()

其次,虽然没有一个好的Minimal, Complete, and Verifiable example清楚地表明你正在做什么,但很难说是肯定的,但我怀疑线程根本无法检索价值。相反,该值是您的UI线程应该在它确定需要启动此后台操作的时间点检索的值,并且该值应该以某种方式传递到后台操作(存储在特定于操作的数据结构,传递给表示操作的async方法等。)


结论:虽然本答案顶部的代码将解决您的具体问题,但我怀疑这个代码(无论它是什么)应该如何编写。您可能应该考虑重新设计,以便更顺利地工作,而无需调用Invoke()