Reputation: 48015
I have this code:
private void buttonStart_Click(object sender, EventArgs e)
{
Task.Factory.StartNew(() => GeneraListaCartelle())
.ContinueWith(t => GeneraListaCartelleCompletata()
, CancellationToken.None
, TaskContinuationOptions.None
, TaskScheduler.FromCurrentSynchronizationContext());
}
private void GeneraListaCartelle()
{
try
{
... some operation ....
}
catch (Exception err)
{
txtErrors.AppendText(err.Message);
}
}
GeneraListaCartelleCompletata()
{
... process finished...
}
and txtErrors
is in the "main" thread (the UI). When I catch an error, the asynch thread cannot write to the UI control, and I get an invalid cross-thread exception
.
Can I dialogate with the UI inside a Thread?
Upvotes: 2
Views: 118
Reputation: 13217
If you are using WinForms, you will need to Invoke your method on the UI-thread like
catch (Exception err)
{
if(this.InvokeRequired){
Action<Exception> act = ((ex) => {
txtErrors.AppendText(ex.Message);
});
this.Invoke(act, new object[] { err });
}
else{
txtErrors.AppendText(err.Message);
}
}
If you are using WPF you will need to
catch (Exception err)
{
if(this.Dispatcher.CheckAccess()){
txtErrors.AppendText(err.Message);
}
else {
Action<Exception> act = ((ex) => {
txtErrors.AppendText(ex.Message);
});
this.Dispatcher.Invoke(act, new object[] { err });
}
}
Upvotes: 4
Reputation: 1601
Pulled this out of an old project where I had to deal with updating the UI from another thread. Should work for you as well.
delegate void addtoValProg();
addtoValProg myDelegate;
myDelegate = new addtoValProg(invokeControl);
private void GeneraListaCartelle()
{
try
{
//... some operation ....
}
catch (Exception err)
{
invokeControl();
}
}
private void invokeControl()
{
if (this.InvokeRequired)
{
this.Invoke(this.myDelegate);
}
else
{
txtErrors.AppendText(err.Message);
txtErrors.Update();
}
}
Upvotes: 1
Reputation: 575
set CheckForIllegalCrossThreadCalls to false in the called form_load event handler
Upvotes: 1
Reputation: 7904
There's an example from msdn:
// This delegate enables asynchronous calls for setting
// the text property on a TextBox control.
delegate void SetTextCallback(string text);
// This method demonstrates a pattern for making thread-safe
// calls on a Windows Forms control.
//
// If the calling thread is different from the thread that
// created the TextBox control, this method creates a
// SetTextCallback and calls itself asynchronously using the
// Invoke method.
//
// If the calling thread is the same as the thread that created
// the TextBox control, the Text property is set directly.
private void SetText(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.textBox1.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else
{
this.textBox1.Text = text;
}
}
Upvotes: 2
Reputation: 223392
if You are targetting WinForm Application then:
try
{
... some operation ....
}
catch (Exception err)
{
if (txtErrors.InvokeRequired)
{
txtErrors.BeginInvoke(new MethodInvoker(
delegate { txtErrors.AppendText(err.Message); })
);
}
}
Upvotes: 3