我在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脱离了条件语句的上下文。
答案 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()
。