相关疑难解决方法(0)

跨线程操作无效:从创建它的线程以外的线程访问控件

我有一个场景.(Windows Forms,C#,.NET)

  1. 有一个主要表单托管一些用户控件.
  2. 用户控件执行一些繁重的数据操作,这样如果我直接调用了 UserControl_Load方法,则UI在加载方法执行的持续时间内变得无响应.
  3. 为了克服这个问题,我在不同的线程上加载数据(尝试尽可能少地更改现有代码)
  4. 我使用了后台工作线程来加载数据,完成后会通知应用程序已经完成了它的工作.
  5. 现在来了一个真正的问题.所有UI(主窗体及其子用户控件)都是在主要主线程上创建的.在usercontrol的LOAD方法中,我基于userControl上的某些控件(如文本框)的值来获取数据.

伪代码看起来像这样:

代码1

UserContrl1_LoadDataMethod()
{
    if (textbox1.text == "MyName") // This gives exception
    {
        //Load data corresponding to "MyName".
        //Populate a globale variable List<string> which will be binded to grid at some later stage.
    }
}
Run Code Online (Sandbox Code Playgroud)

它给出的例外是

跨线程操作无效:从创建它的线程以外的线程访问控件.

为了更多地了解这一点,我做了一些谷歌搜索,并提出了一个建议,如使用下面的代码

代码2

UserContrl1_LoadDataMethod()
{
    if (InvokeRequired) // Line #1
    {
        this.Invoke(new MethodInvoker(UserContrl1_LoadDataMethod));
        return;
    }

    if (textbox1.text == "MyName") // Now it wont give an exception
    {
    //Load data correspondin to "MyName"
        //Populate a globale …
Run Code Online (Sandbox Code Playgroud)

c# multithreading invoke winforms

559
推荐指数
18
解决办法
39万
查看次数

是否适合扩展Control以提供始终如一的安全Invoke/BeginInvoke功能?

在我维护一个严重违反winforms中的跨线程更新规则的旧应用程序的过程中,我创建了以下扩展方法,以便在我发现它们时快速修复非法调用:

/// <summary>
/// Execute a method on the control's owning thread.
/// </summary>
/// <param name="uiElement">The control that is being updated.</param>
/// <param name="updater">The method that updates uiElement.</param>
/// <param name="forceSynchronous">True to force synchronous execution of 
/// updater.  False to allow asynchronous execution if the call is marshalled
/// from a non-GUI thread.  If the method is called on the GUI thread,
/// execution is always synchronous.</param>
public static void SafeInvoke(this Control uiElement, Action updater, bool forceSynchronous)
{
    if …
Run Code Online (Sandbox Code Playgroud)

c# extension-methods controls invoke winforms

33
推荐指数
2
解决办法
8592
查看次数

即使使用InvokeRequired,跨线程操作也无效

我有一个带有自定义控件的表单.

我的表格中有一个方法:

private void SetEnabledOnControls(bool val)
{
  if (InvokeRequired)
  {
      Invoke((Action<bool>)SetEnabledOnControls, val);
  }
  else
  {
       //do the work - iterate over child controls, 
       //and they iterate over their children, etc...
  }
}
Run Code Online (Sandbox Code Playgroud)

在else分支上的方法内部,我得到了提到的异常:
Cross-thread operation not valid: Control 'txtNumber' accessed from a thread other than the thread it was created on.

我的场景实际上有点复杂 - 我只是将其推断为一个例子.实际上发生的是我正在使用WorkflowFoundation - 我在WorkflowApplication中运行StateMachineActivity(CTP1)(它在自己的线程中运行),我订阅了它的事件,并从那里调用SetEnabledOnControls.此外,我正在使用书签来恢复我的工作流程(而且,旁边有MEF,没有涉及场景).

所有这些都与我对InvokeRequired的明显误解无关 - 如果InvokeRequired为false,我有可能有交叉线程异常吗?我没有"手动"创建任何控件 - 它都在设计者放置的Initialize()中.

任何人都可以对此有所了解吗?

谢谢!

编辑 使用GWLlosa建议,我使用了跟踪ThreadId System.Threading.Thread.CurrentThread.ManagedThreadId.现在来了奇怪的部分...... Initialize()中的线程id是10.在传递前2个状态之间,它带有Id 13 - InvokeRequired为true,并且它被正确调用.但是,在第二个状态之后,当它SetEnabledOnControls再次进入13时,但这次InvokeRequired是假的!怎么会!?当然,后来它无法改变儿童控制(这并不奇怪).可能是表格以某种方式改变了它所生活的线程?

编辑2 现在我打电话给:

 if …
Run Code Online (Sandbox Code Playgroud)

c# multithreading .net-4.0 thread-safety winforms

6
推荐指数
1
解决办法
5116
查看次数

"System.InvalidOperationException:该对象目前正在其他地方使用" - 我该如何解决这个问题?

尝试更新图像时出现此错误.这是一个跨线程更新,但我使用.Invoke(),所以这不应该是问题,如果它.

c# exception invoke

4
推荐指数
1
解决办法
3483
查看次数

在创建窗口句柄之前,无法在控件上调用VB.NET Invoke,但是创建了句柄

这是我的情况,有2个类和我的主要表单Form1:

Class1:有一个方法doSomethingAndCall(callback)创建一个新线程Class2:具有动态创建的控件,带有一个触发Class1.doSomethingAndCall(newCallback)的按钮

在代码中它看起来像这样(它从Class2.Button_Click开始):

Class Class1
  public shared sub doSomethingAndCallAsync(state as object)
    Console.WriteLine(Form1.InvokeRequired) 'output: false
    Console.WriteLine(Form1.IsHandleCreated) 'output: false
    Form1.Invoke(state.callback) 'throws System.InvalidOperationException
  end sub

  public shared sub doSomethingAndCall(callback as object)
    System.Threading.ThreadPool.QueueUserWorkItem(AddressOf doSomethingAndCallAsync, New With {.callback = callback})
  end sub
End Class

Class Class2
  Public Delegate Sub doSomethingDelegate()

  Public Sub doSomething()
    Console.WriteLine("success!")
  End Sub

  Public Sub Button_Click(ByVal sender As Object, ByVal e As System.EventArgs)
    Class1.doSomethingAndCall(New doSomethingDelegate(AddressOf doSomething))
  End Sub
End Class
Run Code Online (Sandbox Code Playgroud)

我得到的确切例外是:

在创建窗口句柄之前,无法在控件上调用Invoke或BeginInvoke

并且我可以看到第4行中的console.WriteLine向我显示该表单实际上并未创建.所以我添加了这个处理程序,现在它真的很混乱:

 Private Sub Form1_HandleCreated(sender As Object, e As System.EventArgs) Handles …
Run Code Online (Sandbox Code Playgroud)

vb.net multithreading invoke winforms

3
推荐指数
1
解决办法
2968
查看次数

不可预知的跨线程异常

在执行我的win表单应用程序时,我将获得一个跨线程异常似乎是一个随机的机会.以下是我试图管理它的方法:

private void ToOutput(string s)
{
    if (!this.IsHandleCreated)
        this.CreateHandle();

    if (FormOutputArea.InvokeRequired)
    {
        FormOutputArea.Invoke(new Action(delegate ()
        {
            FormOutputArea.AppendText(s + Environment.NewLine);
        }));
    }
    else
    {
        FormOutputArea.AppendText(s + Environment.NewLine);
    }
}
Run Code Online (Sandbox Code Playgroud)

它似乎InvokeRequired并不总是准确的.我尝试BeginInvoke了相同的结果.

编辑:即使我检查IsHandleCreated并InvokeRequired使用断点,它们也设置为true,但else条件的分支仍然执行.

这是一个截图,显示现在抛出异常的位置:

在此输入图像描述

.net c# multithreading thread-safety

2
推荐指数
1
解决办法
147
查看次数