Cross-Threading Exception writing to RTF Box
-
2012年4月13日 15:08
Hello,
I am trying to write an application that is multi-threaded so that the UI is updated separately from the processing thread.
It seems as if toolstripstatuslabel updates work fine but updating a RTF box on the UI causes a cross-thread exception.
Does anyone know why the two and treated differently?
Regards,
Steve
- 移動 CoolDadTxMVP 2012年4月13日 17:43 Winforms related (From:Visual C# General)
すべての返信
-
2012年4月13日 15:12ToolStripItems do not inherit from System.Windows.Forms.Control, so they do not have cross-thread access issues. RichTextBoxes do, so you have to call Invoke() on them.
-
2012年4月13日 15:19
IF you have some code that would like to "write" some data from a new thread to UI thread, you can start thinking of using delegates, and Invoke (InvokeRequited) method, to update control on UI thread.Mitja
- 回答の候補に設定 Jason Dot WangMicrosoft Contingent Staff, Moderator 2012年4月16日 4:43
- 回答としてマーク Jason Dot WangMicrosoft Contingent Staff, Moderator 2012年4月23日 3:11
-
2012年4月13日 16:14
Hi,
Also,
Yes, ToolStripStatusLabel does not derive from the control. It seems by initial search I find there are few topics how to avoid Cross-Thread Exception for ToolStripStatusLabel.
I would suggest for your case you can use BackGroundWorker, which follows EAP(event based asynchronous pattern) and specially for this purpose and is discussed in following post
http://social.msdn.microsoft.com/Forums/eu/csharpgeneral/thread/6a937def-a07c-47ca-8586-814b14f2afd3
I hope this helps you..
If this post answers your question, please click "Mark As Answer". If this post is helpful please click "Mark as Helpful".
- 編集済み Kris444 2012年4月13日 16:16
- 回答の候補に設定 Jason Dot WangMicrosoft Contingent Staff, Moderator 2012年4月16日 4:44
-
2012年4月13日 16:19
The problem you are having is because one thread can't access objects running in another thread directly without using a delegate. This is why you are getting the cross thread exception. Here is a loose interpretation of this logic, and take note, it was written a few years ago. There are probably better ways to implement threading today.
Firstly, create a delegate
public delegate void UpdateLabelCallBack(string strStatus);
Then create a method for updating the label.
private void UpdateStatus(string _Status) { lblProcessHidden.Text = _Status.Trim(); lblProcess.Text = lblProcessHidden.Text; }In the process button logic, the new thread is created that will execute the long running task. (Note that I am passing parameters to this thread which you might not want to do. Also take note, the declaration of the thread isn't shown. So declare the variable th1 first.
string p1 = glbSheetName;
object[] parameters = new object[] { p1 };th1 = new Thread(new ParameterizedThreadStart(this.ExecuteProcess));
th1.Start(parameters);
Then in the method called ExecuteProcess() which runs on the new thread performing the long running task, I update a label on my main windows form (GUI) by invoking the following code:
lblProcessHidden.Invoke(new UpdateLabelCallBack(this.UpdateStatus), new Object[] { "Processing Data..." });This then calls the delegate from the new thread and passes the string to update the text on the label on the UI.
But after all this talk about Threading, might I suggest another solution? Why don't you take a look into tasks? It also exists in the Threading Namespace, but if you are using the .NET Framework 4, read this post on Code Project called Multi core programming using Task Parallel Library with .NET 4.0 written by Varun Manipal.
I hope that I could have helped you a bit. Please let me know if you need any more information. Good luck :)
- 回答の候補に設定 Jason Dot WangMicrosoft Contingent Staff, Moderator 2012年4月16日 4:44
-
2012年4月13日 16:24
How about something like???
delegate void updateRichTextboxTextDelegate(string newItem); private void updateRichTextboxText(string newText) { if (rtBox.InvokeRequired) { // this is a non UI thread updateRichTextboxTextDelegate del = new updateRichTextboxTextDelegate(updateRichTextboxText); rtBox.Invoke(del, new object[] { newText }); } else { // this is UI thread rtBox.Text = newText; } } private void sommeEvent(object sender, EventArgs e) { updateRichTextboxText("Text text"); }- 回答の候補に設定 daktmacfan 2012年4月13日 17:03
- 回答としてマーク Jason Dot WangMicrosoft Contingent Staff, Moderator 2012年4月23日 3:07
-
2012年4月13日 16:37Looks good to me.
-
2012年4月13日 17:43
Hello,
You should know the risks before using InvokeRequired and check whether the handle was actually created; otherwise, it may fail on you.
It's best advice to either use SyncheonizedContext (WindowsFormsSynchronizationContext in WinForms) or the TaskSchedular.FromSynchronizedContext()
Here is a complete example that I already posted in another thread using InvokeRequired.
namespace Threading.InvokeRequired { using System; using System.Diagnostics; using System.Globalization; using System.Threading; using System.Windows.Forms; public partial class AppMain : Form { private readonly Action<int> updateCounter; public AppMain() { InitializeComponent(); Debug.WriteLine("UI running on thread '{0}'.", Thread.CurrentThread.ManagedThreadId); updateCounter = UpdateCounter; } private void Count_Click(object sender, EventArgs e) { updateCounter.BeginInvoke(0, null, null); } private void UpdateCounter(int i) { // Checks whether we have a handle otherwise InvokeRequired might fail if (!IsHandleCreated) { // Do something } // Checks whether the current thread and the thread that the control was created on are equal if (InvokeRequired) { Debug.WriteLine("Executing on thread '{0}'.", Thread.CurrentThread.ManagedThreadId); // Just for the example so we would have a chance to see on what thread it executes the work // Thread.Sleep(3000); while (true) { IAsyncResult r = BeginInvoke(updateCounter, i++); r.AsyncWaitHandle.WaitOne(); } } Debug.WriteLine("Updating on thread '{0}'.", Thread.CurrentThread.ManagedThreadId); // Updating the counter uxCounter.Text = i.ToString(CultureInfo.InvariantCulture); } } }
Eyal (http://shilony.net), Regards.
- 編集済み Eyal Shilony 2012年4月13日 18:15
- 回答の候補に設定 Jason Dot WangMicrosoft Contingent Staff, Moderator 2012年4月16日 4:45
- 回答としてマーク clipsemeister 2012年4月20日 22:04

