【问题标题】:CrossThreadMessagingException while using backgroundworker windows forms [duplicate]使用 backgroundworker windows 窗体时出现 CrossThreadMessagingException [重复]
【发布时间】:2015-03-10 12:33:42
【问题描述】:

我有一个 Windows 窗体应用程序和一个调用函数的按钮

我正在将大文件从一个地方复制到另一个地方。

这需要很长时间,所以我决定使用进度条。 我需要通过单击按钮调用后台进程

copyItems() 函数遍历列表项并从另一个位置复制这些项。它又调用一个函数CopyListItem 复制一个项目。

我在 UI 中设置了一个文本框值,但它返回一个

发生异常“Microsoft.VisualStudio.Debugger.Runtime.CrossThreadMessagingException”`

如何在backgroundworker todo事件中调用复制功能
当我在 click 事件中调用 runworkerasync 方法时出现错误

    private void btnCopyItems_Click(object sender, EventArgs e)
    {
        backgroundWorker1.RunWorkerAsync();
    }

我创建了一个类

public partial class WorkerItem
{
    Helper Helper = new Helper();
    Complaints comp = new Complaints();
    public void CopyItem(SPListItem sourceItem, string destinationListName, string destServerURL)
    {
        //Copy sourceItem to destinationList
        try
        {
           // copies file from one location to another
        }
        catch (Exception ex)
        {
            Helper.LogtoList("Copy List ", string.Format("  {0} Message {1} Source {2} Stack trace {3}", ex.InnerException.ToString(), "Message " + ex.Message + "Source" + ex.Source + "Stack trace" + ex.StackTrace));
        }
    }
}

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    progressBar1.Value = e.ProgressPercentage;
    this.Text=e.ProgressPercentage.ToString();
}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    try
    {
        WorkerItem workerItem = (WorkerItem)e.Argument;

        // check if the site valid
        Helper.siteName = txtSite.Text;
        {                          
            progressBar1.Maximum = itemscoll.Count;
            foreach (SPListItem sourceItem in itemscoll)
            {
                date = sourceItem["Date_x0020_Created"].ToString();
                if (!string.IsNullOrEmpty(date))
                {                               
                    workerItem.CopyItem(sourceItem, Helper.destinationListName, Helper.destServerURL);
                }
            }
        }

        Cursor.Current = Cursors.Default;
        MessageBox.Show(string.Format("Items Copied {0}", Helper.ItemsCopied.ToString()));
    }
    catch (Exception ex)
    {
        Helper.LogtoList("Main Function ", string.Format("{0} Message {1} Source {2} Stack trace {3}", ex.InnerException.ToString(), "Message " + ex.Message + "Source" + ex.Source + "Stack trace" + ex.StackTrace));
    }
}

【问题讨论】:

    标签: c# .net winforms c#-4.0 c#-3.0


    【解决方案1】:

    您收到异常的原因是因为您在 BackgroundWorker 的 DoWork 事件中设置了 progressBar1.Maximum = itemscoll.Count;
    您的 DoWork 事件中不应发生 UI 更改,即是 ProgressChanged 事件的用途。

    您的代码中也没有任何迹象表明您正在向主线程报告任何进度。

    你应该处理你的例子的方式如下:

    private void btnCopyItems_Click(object sender, EventArgs e)
    {
      // Set the progressBar1.Maximum here before we call the background worker
      // This is what caused your exception, since it is an UI element that you are trying to change
      // inside your BackgroundWorker thread
      progressBar1.Maximum = 100;             // % based (Could be set onces and always left at 100)
      progressBar1.Maximum = itemscoll.Count; // x/y based
      // Either we use a percentage based progressbar or an x/y progressbar.
      // !!!! Choose one and use the appropriate values for it !!!!
    
      backgroundWorker1.RunWorkerAsync();
    }
    
    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
      try
      {
        WorkerItem workerItem = (WorkerItem)e.Argument;
    
        Helper.siteName = txtSite.Text;
        {
          // Variable for our progress calculation
          double curProgress; // % based
    
          // Since we need to report progress, let us use a for-loop instead of a foreach-loop
          for (int i = 0; i < itemscoll.Count-1; i++)
          {
            SPListItem sourceItem = itemscoll[i];
            date = sourceItem["Date_x0020_Created"].ToString();
            if (!string.IsNullOrEmpty(date))
            {
              workerItem.CopyItem(sourceItem, Helper.destinationListName, Helper.destServerURL);
            }
    
            // Calculate the current progress and call the ReportProgress event of our BackgroundWorker
            curProgress = ((double)i / (double)itemscoll.Count) * 100;                // % based
            ((BackgroundWorker)sender).ReportProgress(Convert.ToInt32(curProgress));  // % based
    
            // If we only go x/y progress based, then just send back our current state
            ((BackgroundWorker)sender).ReportProgress(0, i);  // x/y based
          }
        }
    
        Cursor.Current = Cursors.Default;
        MessageBox.Show(string.Format("Items Copied {0}", Helper.ItemsCopied.ToString()));
      }
      catch (Exception ex)
      {
        Helper.LogtoList("Main Function ", string.Format("{0} Message {1} Source {2} Stack trace {3}", ex.InnerException.ToString(), "Message " + ex.Message + "Source" + ex.Source + "Stack trace" + ex.StackTrace));
      }
    }
    
    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
      // % based
      progressBar1.Value = e.ProgressPercentage;
      this.Text = e.ProgressPercentage.ToString();
    
      // x/y based
      progressBar1.Value = Convert.ToInt32(e.UserState);
      this.Text = Convert.ToInt32(e.UserState).ToString();
    }
    

    注意两种不同的进度报告方法!
    一种使用基于百分比的报告,另一种使用基于 x/y 的报告。
    您想使用哪一个取决于您,但您需要选择一个并使用它

    有关 BackgroundWorker 的更多信息,请访问:
    MSDN: BackgroundWorker Class
    MSDN: How to: Run an Operation in the Background

    最后一点:
    您在 BackgroundWorker 中使用 MessageBox.Show,不建议这样做,您应该停止工作线程并将适当的错误返回到主线程以显示。

    【讨论】:

      【解决方案2】:

      使用以下方法之一来避免此异常。

      this.Invoke((MethodInvoker)delegate
      {
                          //code here you required
      });
      

      //---------或以下代码----------

      this.BeginInvoke((MethodInvoker)delegate
      {
                            //code here you required
       });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多