使用 backgroundworker windows 表单时出现 CrossThreadMessagingException
CrossThreadMessagingException while using backgroundworker windows forms
我有一个 windows 表单应用程序和一个调用函数的按钮
我正在将大文件从一个地方复制到另一个地方。
花了很长时间,所以我决定使用进度条。
我需要从按钮点击调用后台进程
copyItems()
函数遍历列表项并从另一个地方复制项。它依次调用一个函数 CopyListItem
来复制一项。
我在 UI 中设置了一个文本框值,但它 returns 和
An exception 'Microsoft.VisualStudio.Debugger.Runtime.CrossThreadMessagingException' occurred`
如何在 backgroundworker todo 事件中调用 copy 函数
当我在点击事件中调用 runworkerasync 方法时,出现错误
private void btnCopyItems_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
我创建了一个class
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));
}
}
使用以下方法之一来避免此异常。
this.Invoke((MethodInvoker)delegate
{
//code here you required
});
//------------或下面的代码------------
this.BeginInvoke((MethodInvoker)delegate
{
//code here you required
});
您收到异常的原因是因为您在 BackgroundWorker 的 DoWork
事件中设置了 progressBar1.Maximum = itemscoll.Count;
。
没有 UI 更改 应该发生在您的 DoWork 事件中,这就是 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
,不建议这样做,您应该停止工作线程并 return 向主线程显示适当的错误。
我有一个 windows 表单应用程序和一个调用函数的按钮
我正在将大文件从一个地方复制到另一个地方。
花了很长时间,所以我决定使用进度条。 我需要从按钮点击调用后台进程
copyItems()
函数遍历列表项并从另一个地方复制项。它依次调用一个函数 CopyListItem
来复制一项。
我在 UI 中设置了一个文本框值,但它 returns 和
An exception 'Microsoft.VisualStudio.Debugger.Runtime.CrossThreadMessagingException' occurred`
如何在 backgroundworker todo 事件中调用 copy 函数
当我在点击事件中调用 runworkerasync 方法时,出现错误
private void btnCopyItems_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
我创建了一个class
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));
}
}
使用以下方法之一来避免此异常。
this.Invoke((MethodInvoker)delegate
{
//code here you required
});
//------------或下面的代码------------
this.BeginInvoke((MethodInvoker)delegate
{
//code here you required
});
您收到异常的原因是因为您在 BackgroundWorker 的 DoWork
事件中设置了 progressBar1.Maximum = itemscoll.Count;
。
没有 UI 更改 应该发生在您的 DoWork 事件中,这就是 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
,不建议这样做,您应该停止工作线程并 return 向主线程显示适当的错误。