我很难找到是否可以从另一个元素在C#表单元素上执行虚拟单击,并等待它完成后再继续。
作为一个例子(不幸的是不完整),我想做的是,
private async void btn_my_Click(object sender, EventArgs e)
{
await Task.Run(() => radio_button_special.PerformClick()); // https://stackoverflow.com/q/14024963
// once this is done, proceed with rest of processing
do_rest_of_processing();
}
当我在运行中单击按钮时,VS 2019会出现“InvalidOperationException:跨线程操作无效:控件'radio_button_special'从创建它的线程以外的线程访问。”
但是,如果我只是在Visual Studio debug之外运行exe,按钮似乎可以工作(即,我可以在应用程序中看到,radio_button_special.PerformClick()首先完成,do_rest_of_processing()在之后运行-我没有得到像那样运行的显式异常,所以它似乎像我想象的那样工作)。
但是这个异常让我害怕,所以我想摆脱它-我已经尝试过这样的补救措施,我已经尝试过从SO上的其他片段构建:
private async void btn_my_Click(object sender, EventArgs e)
{
// first, I want to call the function otherwise called
// when the radio button is clicked, and wait for it to complete
radio_button_special.Invoke((MethodInvoker)async delegate
{
await Task.Run(() => radio_button_special.PerformClick()); // https://stackoverflow.com/q/14024963
});
// once this is done, proceed with rest of processing
do_rest_of_processing();
}
现在,这个函数已经在VS 2019 IDE中给出了警告:
警告CS 1998:此异步方法缺少'await'运算符,将同步运行。考虑使用“await”运算符等待非阻塞API调用,或使用“await Task.Run(...)"在后台线程上执行CPU绑定的工作。
.如果我调试运行示例,我会得到堆栈跟踪:
System.Reflection.TargetInvocationException
HResult=0x80131604
Message=Exception has been thrown by the target of an invocation.
Source=mscorlib
StackTrace:
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
...
at System.Windows.Forms.Application.Run(Form mainForm)
at my_test.Program.Main() in D:\work\bbs\BBS_DEV\BAPS_git\my_test\Program.cs:line 28
This exception was originally thrown at this call stack:
System.Windows.Forms.Control.Handle.get()
System.Windows.Forms.Control.InternalHandle.get()
System.Windows.Forms.Control.Update()
System.Windows.Forms.ButtonBase.ResetFlagsandPaint()
System.Windows.Forms.RadioButton.PerformClick()
my_test.main_form.btn_my_Click.AnonymousMethod__122_1() in main_form.cs
System.Threading.Tasks.Task.InnerInvoke()
System.Threading.Tasks.Task.Execute()
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Threading.Tasks.Task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks.Task)
...
[Call Stack Truncated]
Inner Exception 1:
InvalidOperationException: Cross-thread operation not valid: Control 'radio_button_special' accessed from a thread other than the thread it was created on.
所以,基本上和之前一样的问题。
那么,我如何调用C#表单组件处理程序(例如,单击)函数,等待它完成,然后调用另一个函数-而不会引发异常?
2条答案
按热度按时间bvjveswy1#
如果你只是想从另一个方法调用一个方法,那么这将起作用:
Task.Run
队列在线程池中工作,这里是不正确的。如果您有较长的工作要做,那么在线程池线程上运行该工作对用户更好。在这种情况下,正确的解决方案是重构代码,以便有另一个方法可以由单选按钮单击和此按钮单击调用。
uajslkp62#
Task.Run
将给予在线程池线程上运行的方法排队。因此,即使执行了调用,您仍在从另一个线程访问控件。相反,您应该在Task.Run
中调用Control.Invoke
。编辑:OP海报的工作是: