Reputation: 2156
I've a Form with many tabs and I want to write to them in the same time from many threads
(UI BackGroundWorker
etc.)
I've written this code and it is working on main tab ( the one that is visible when app starts )
public struct Struct_Append
{
public RichTextBox Screen;
public string Message;
public Color Color;
}
public void AppendAllTextAllScreen (Struct_Append append )
{
RichTextBox screenToPrint = append.Screen;
Font font = new Font("Tahoma", 8, FontStyle.Regular);
if (screenToPrint.InvokeRequired) //&& this.Visible)
{
append.Message = append.Message + "\n";
try
{
this.Invoke(new Action<Struct_Append>(AppendAllTextAllScreen), new object[] {
append });
}
catch(Exception ex)
{
//handle exception
}
return;
}
append.Message = append.Message + "\n";
screenToPrint.SelectionFont = font;
screenToPrint.SelectionColor = append.Color;
screenToPrint.AppendText(append.Message);
}
It is working from any thread , but once I set the screen to some of the other tabs , and fire it
Struct_Append structAppend1 = new Struct_Append();
structAppend1.Screen = scrnSta1;
structAppend1.Color = Color.Bisque;
structAppend1.Message = "THIS IS A TEST";
AppendAllTextAllScreen(structAppend1);
VisualStudio2013 just get stuck and restart it self!!!!
BUT when I run it without DEBUG it runs fine
EDIT code that I used that spawn the ERROR
this is the I used to test the appendText
method above
private async void DoSomthing()
{
Task.Run(() =>
{
_Append structAppend1 = new _Append();
structAppend1.Screen = ScrnSta1; ;
structAppend1.Color = Color.Bisque;
structAppend1.Message = "THIS IS A TEST";
for (int i = 0; i < 5; i++)
{
AppendAllTextAllScreen(structAppend1);
}
});
Task.Run(() =>
{
_Append structAppend = new _Append();
structAppend.Color = Color.Aquamarine;
structAppend.Message = "THIS IS A TEST";
structAppend.Screen = ScrnSta2;
for (int j = 0; j < 5; j++)
{
AppendAllTextAllScreen(structAppend);
}
});
}
scrnsta1/2 are two seperated tabs in my Form
(main UI thread), and I call this method from there(UI thread)
what am I missing here ?
Upvotes: 2
Views: 1365
Reputation: 3686
I would recommend to continue the tasks on the UI thread without using invoke. It is much safer and less error prone: Task continuation on UI thread
Task UITask= task.ContinueWith(() =>
{
this.TextBlock1.Text = "Complete";
}, TaskScheduler.FromCurrentSynchronizationContext());
Upvotes: 1
Reputation: 17605
To my understanding, access to Windows Forms controls from a different thread must be done by means of the Invoke method of Control
, which needs the definition of suitable delegates. In your example, these delegates would be basically the lambda expressions used in the implementation of DoSometing
.
Upvotes: 1