相关疑难解决方法(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万
查看次数

自动化InvokeRequired代码模式

我已经痛苦地意识到需要在事件驱动的GUI代码中编写以下代码模式的频率,其中

private void DoGUISwitch() {
    // cruisin for a bruisin' through exception city
    object1.Visible = true;
    object2.Visible = false;
}
Run Code Online (Sandbox Code Playgroud)

变为:

private void DoGUISwitch() {
    if (object1.InvokeRequired) {
        object1.Invoke(new MethodInvoker(() => { DoGUISwitch(); }));
    } else {
        object1.Visible = true;
        object2.Visible = false;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是C#中的一个尴尬模式,无论是记忆还是打字.有没有人提出某种捷径或构造,在一定程度上自动化?如果有一种方法可以将函数附加到执行此检查的对象,而不必经历所有这些额外的工作,如object1.InvokeIfNecessary.visible = true类型快捷方式,那就太酷了.

上一页答案已经讨论的只是打电话的invoke()每次不切实际,甚则调用()语法既效率低下,仍然尴尬应对.

那么,有没有人想出任何捷径?

c# multithreading thread-safety invokerequired winforms

178
推荐指数
7
解决办法
13万
查看次数

是否适合扩展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
查看次数

InvalidOperationException - 对象当前正在其他地方使用

我已经完成了这个问题,但没有帮助.

这里的情况不同.我正在使用Backgroundworkers.第一个backgroundworker开始操作用户的图像输入和firstbackgroundworker_runworkercompleted()我正在使用调用其他3个后台工作者

 algo1backgroundworker.RunWorkerAsync();
 algo2backgroundworker.RunWorkerAsync();
 algo3backgroundworker.RunWorkerAsync();
Run Code Online (Sandbox Code Playgroud)

这是每个的代码:

algo1backgroundworker_DoWork()
{
 Image img = this.picturebox.Image;
 imgclone = img.clone();
 //operate on imgclone and output it
}

algo2backgroundworker_DoWork()
{
 Image img = this.picturebox.Image;
 imgclone = img.clone();
 //operate on imgclone and output it
}
Run Code Online (Sandbox Code Playgroud)

类似的操作在其他algo*backgrougrondworker_doWork()中完成.

现在有时我得到"InvalidOperationException - 对象目前正在其他地方使用".它很随意.我有时会在algo1backgroundworker_DoWork中获取此信息,有时在algo2backgroundworker_DoWork中,有时在Application.Run(new myWindowsForm())中获取;

我不知道发生了什么事.

.net c# backgroundworker winforms

26
推荐指数
3
解决办法
3万
查看次数

从单独的线程访问表单的控件

我正在练习线程并遇到了这个问题.情况是这样的:

  1. 我在一个表单上有4个进度条,一个用于下载文件,一个用于显示页面加载状态等...

  2. 我必须从一个单独的线程控制每个ProgressBar的进度.

问题是,我得到一个出现InvalidOperationException它说

跨线程操作无效:控制'progressBar1'从其创建的线程以外的线程访问.

我在这种方法上错了,还是有人能告诉我如何实现这个?

c# multithreading winforms

13
推荐指数
4
解决办法
5万
查看次数

是否需要InvokeRequired?

我的同事喜欢这样做

if (!listbox1.InvokeRequired)
    listbox1.Items.Add(Container.error_message);
else
    listbox1.Invoke((MethodInvoker)delegate
    {
        listbox1.Items.Add(Container.error_message);
    });
Run Code Online (Sandbox Code Playgroud)

他为什么要检查InvokedRequired?仅使用此声明会更好吗?

    listbox1.Invoke((MethodInvoker)delegate
    {
        listbox1.Items.Add(Container.error_message);
    });
Run Code Online (Sandbox Code Playgroud)

c# invoke

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

必须使用Control.Invoke与在单独线程上创建的控件进行交互

下面是在紧凑框架3.5中启动线程的方法

public ScanEntry(string scanId)
{
   InitializeComponent();
    _scanId = scanId;
    //reader = deviceFactory.Create();
    //reader.YMEvent += new ScanEventHandler(reader_Reading);
    //reader.Enable();
 }


private void CasesEntry_Load(object sender, EventArgs e)
{
      caseCounterLabel.Text = cases.Count.ToString();
      scanIdValueLabel.Text = _scanId;
}



internal void menuItemNewScan_Click(object sender, EventArgs e)
{
       System.Threading.ThreadStart threadDelegate = new System.Threading.ThreadStart(ScanEvents);
       System.Threading.Thread newThread = new System.Threading.Thread(threadDelegate);
       newThread.Start();
}
Run Code Online (Sandbox Code Playgroud)

在线程上调用下面的方法

private void ScanEvents()
{

  try
  {

     //some other codes     
      if (scanIdValueLabel.InvokeRequired)
     {
          scanIdValueLabel.Invoke((Action)(() => scanIdValueLabel.Text = "value"));
      }  


     attributeNode = docEventFile.CreateNode(XmlNodeType.Element, "Attribute", string.Empty);
     XMLUtils.CreateAttribute(docEventFile, attributeNode, "name", "SCANID");
     XMLUtils.CreateAttribute(docEventFile, …
Run Code Online (Sandbox Code Playgroud)

.net c# compact-framework

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