Object in use System.InvalidOperationException' - c#

I have problems calling Form objects from another class.
In Form class I have this:
public void reloadMapOverlay(GMapOverlay overlay)
{
try
{
Invoke(new Action(() => this.map_Box.Overlays.Add(overlay)));
}
catch (Exception e)
{
Console.WriteLine("reloadMapOverlay: {0}", e);
this.setError("reloadMapOverlay: " + e);
}
}
And in another class (Map_custom.cs):
route.Points.Add(coords.get_position());
overlay.Routes.Add(route);
mainForm.reloadMapOverlay(overlay);
When mainForm.reloadMapOverlay executes, vb gives me and object in use an exception
System.InvalidOperationException
in overlay object.
What can I can do?

i try adding dispacher in mainForm, ->
public Dispatcher dispacher = Dispatcher.CurrentDispatcher;
public void reloadMapOverlay(GMapOverlay overlay)
{
try
{
dispacher.Invoke(new Action(() => this.map_Box.Overlays.Add(overlay)));
}
catch (Exception e)
{
Console.WriteLine("reloadMapOverlay: {0}", e);
this.setError("reloadMapOverlay: " + e);
}
}
and nothing.
i have
public void reloadMapOverlay(GMapOverlay overlay)
{
try
{
Invoke(new Action(() => this.map_Box.Overlays.Add(overlay)));
}
catch (Exception e)
{
Console.WriteLine("reloadMapOverlay: {0}", e);
this.setError("reloadMapOverlay: " + e);
}
} in mainForm,
then, in another class (Map_Custom.cs) i have a function
public void addRoute()
{
if (!coords.isWrongCoords())
{
Console.WriteLine("Route");
route.Points.Add(coords.get_position());
overlay.Routes.Add(route);
mainForm.reloadMapOverlay(overlay);
}
}
and in mainFrom i have a function (inside one thread) where i call
Thread addRoute = new Thread(new ThreadStart(map.addRoute));
addRoute.IsBackground = true;
addRoute.Start();

Related

How to show waiting Gif image during form load event

i have one form which is doing some long process on form load event,
So i want to show One Gif image "Please Wait" during form load event.
below is code.
private void frmWaitShow()
{
try
{
frmWaitwithstatus objWait = new frmWaitwithstatus();// this form has Gif Image for Processing
objWait.lblStatus.Text = "Processing Request, Please wait...";
objWait.ShowDialog();
}
catch (Exception ex)
{
Logger.SystemException(ex);
Logger.FTSError(" ERROR :" + ex.Message + "frmTest || frmWaitShow");
}
}
Thread oThread;
private void frmTest_Load(object sender, EventArgs e)
{
try
{
oThread = new Thread(new ThreadStart(frmWaitShow));
oThread.Start();
//Functions for Connection with devices
if (LoadDatafromDB() == false) return;
if (ElectTestLoad() == false) return;
if (PowerOnSelfTest() == false) { return; }
InitiControlsElectTest();
SetSystemMode(SystemMode.ElectricalMode);
oThread.Abort();
}
catch (Exception ex)
{
oThread.Abort();
Logger.SystemException(ex);
}
}
after Thread.start() my debugger go one one step in each thread main and one i created but after it go to below line.
frmWaitwithstatus.cs constructor first line
public frmWaitwithstatus()
it stop execute my Thread and execute all function of main thread once Main Thread execution complete after then only it start execute my thread (which is Gif processing image).
Using the async/await pattern will made this an easy task and every form will work on UI thread:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private async void Form1_Load(object sender, EventArgs e)
{
// async show loading form dialog
var loadingForm = new LoadingForm();
var loadingDialogTask = this.InvokeAsync(loadingForm.ShowDialog);
// async loading data
var data = await LoadDataAsync();
listBox1.DataSource = data;
loadingForm.Close();
await loadingDialogTask;
}
private async Task<ICollection<string>> LoadDataAsync()
{
// fake work load
await Task.Delay(4000).ConfigureAwait(false);
return Enumerable.Range(1,20000).Select(e => e.ToString()).ToList();
}
}
Needed async extension for the controls:
public static class ControlAsyncExtensions
{
public static Task InvokeAsync(this Control control, Action action)
{
var tcs = new TaskCompletionSource<bool>();
control.BeginInvoke(new Action(() =>
{
try
{
action();
tcs.SetResult(true);
}
catch (Exception ex)
{
tcs.SetException(ex);
}
}
));
return tcs.Task;
}
public static Task<T> InvokeAsync<T>(this Control control, Func<T> action)
{
var tcs = new TaskCompletionSource<T>();
control.BeginInvoke(new Action(() =>
{
try
{
tcs.SetResult(action());
}
catch (Exception ex)
{
tcs.SetException(ex);
}
}
));
return tcs.Task;
}
}

SynchronizationContext and DispatcherUnhandledException

I am having a case where an exception thrown in UI thread doesn't get catched in the calling thread.
using System;
using System.Diagnostics;
using System.Threading;
using System.Windows;
namespace SynchronisationContextAndExceptionWPF
{
public partial class MainWindow : Window
{
private readonly SynchronizationContext _synchronizationContext;
public MainWindow()
{
InitializeComponent();
_synchronizationContext = SynchronizationContext.Current;
}
private void Button_OnClick(object sender, RoutedEventArgs e)
{
try
{
_synchronizationContext.Send(
x =>
{
try
{
DoSomethingOnUiThreadThatThrowsException();
}
catch (Exception)
{
Debug.WriteLine("Catched Exception in thread that threw it.");
throw;
}
}, null);
}
catch (Exception)
{
Debug.WriteLine("Catched Exception in thread that calles Send-Method.");
throw;
}
}
private static void DoSomethingOnUiThreadThatThrowsException()
{
throw new Exception("Any Exception...");
}
}
}
First I thought that cannot possible (all documentation I found said that I can catch exceptions there).
After some reasearch I found the problem: My application uses an UnhandledExceptionHandler. That handles the DispatcherUnhandledException-Event. I am showing some information to the user and set e.Handled = true;:
using System.Diagnostics;
using System.Windows;
using System.Windows.Threading;
namespace SynchronisationContextAndExceptionWPF
{
public partial class App : Application
{
public App()
{
DispatcherUnhandledException += App_DispatcherUnhandledException;
}
private static void App_DispatcherUnhandledException(
object sender,
DispatcherUnhandledExceptionEventArgs e)
{
Debug.WriteLine("Catched Exception in UnhandledExceptionHandler.");
// This line makes the difference:
e.Handled = true;
}
}
}
So the question: why is the DispatcherUnhandledException-Event raised even if I handle it?
How would you solve this situation?
If you have a lot of controls, you can generate a new class which remenbers the special exception variable. So you only need to change the initialization of your _synchronizationContext (hopefully only once at your base class of your controls).
public partial class MainWindow : Window
{
private readonly MySynchronizationContext _synchronizationContext;
public MainWindow()
{
InitializeComponent();
_synchronizationContext = new MySynchronizationContext(SynchronizationContext.Current);
}
private void button_Click(object sender, RoutedEventArgs e)
{
try
{
_synchronizationContext.Send(
x =>
{
DoSomethingOnUiThreadThatThrowsException();
}, null);
}
catch (Exception)
{
Debug.WriteLine("Catched Exception in thread that calles Send-Method.");
throw;
}
}
private static void DoSomethingOnUiThreadThatThrowsException()
{
throw new Exception("Any Exception...");
}
}
class MySynchronizationContext
{
SynchronizationContext innerContext;
public MySynchronizationContext(SynchronizationContext ctx)
{
innerContext = ctx;
}
public virtual void Send(SendOrPostCallback d, object state)
{
Exception threadException = null;
try
{
innerContext.Send(_ =>
{
try
{
d.Invoke(state);
}
catch (Exception exception)
{
threadException = exception;
}
}, null);
}
catch (Exception ex)
{
}
if (threadException != null)
{
throw new Exception("Synchronization error", threadException);
}
}
}
Inside your lambda expression you can set an Exception variable and check this variable later at the calling thread. If it was set, then throw exception at calling thread.
private void button_Click(object sender, RoutedEventArgs e)
{
Exception threadException = null;
try
{
_synchronizationContext.Send(
x =>
{
try
{
DoSomethingOnUiThreadThatThrowsException();
}
catch (Exception ex)
{
Debug.WriteLine("Catched Exception in thread that threw it.");
threadException = ex;
//throw; --> don't throw exception here; otherwise you will get DispatcherUnhandledException twice.
}
}, null);
}
catch (Exception)
{
Debug.WriteLine("Catched Exception in thread that calles Send-Method.");
throw;
}
if(threadException != null)
{
Debug.WriteLine("Catched Exception in thread that calles Send-Method.");
throw threadException; //throw you previously catched exception here.
}
}
Kind Regards,
Daniel

Thread that talk with UI?

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?
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 });
}
}
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); })
);
}
}
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;
}
}
set CheckForIllegalCrossThreadCalls to false in the called form_load event handler
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();
}
}

Thread Exception handling

I have a function in my logical Layer that insert information by another thread and I want if unknown exception happen in that thread throw it but the problem is that in my application UnhandledExceptionEventHandler that get general exception it gives this error and i also don't want to shutdown the application:
The calling thread must be STA, because many UI components require this
///////////////////// this is my function in logical layer //////////
public string MahaleInsert(Mahales Mahale)
{
Thread t = new Thread(delegate()
{
try
{
Mahale.OutMessage = DA_Agency.MahaleInsertDB(Mahale);
Mahale.OutMessage = "SuccessInsert";
}
catch (Exception ex)
{
if (ex.Message.ToLower().Contains("violation of unique key constraint"))
Mahale.OutMessage = "MahaleInsUniqueError";
else
throw;
}
});
t.Start();
t.Join();
return Mahale.OutMessage;
}
//////////////////////////// this in my aplication level //////////////////
void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
try
{
string messsage = GeneralMethod.CatchException(e.ExceptionObject as Exception);
MessageClass.MessageBox(messsage);
}
catch
{
}
}
Try To do the following :
public string MahaleInsert(Mahales Mahale)
{
Thread t = new Thread(new ThreadStart(ThreadBody));
t.Start();
t.Join();
return Mahale.OutMessage;
}
[STAThread]
void ThreadBody()
{
try
{
Mahale.OutMessage = DA_Agency.MahaleInsertDB(Mahale);
Mahale.OutMessage = "SuccessInsert";
}
catch (Exception ex)
{
if (ex.Message.ToLower().Contains("violation of unique key constraint"))
Mahale.OutMessage = "MahaleInsUniqueError";
else
throw;
}
}
//////////////////////////// this in my aplication level //////////////////
void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
try
{
string messsage = GeneralMethod.CatchException(e.ExceptionObject as Exception);
MessageClass.MessageBox(messsage);
}
catch
{
}
}

How to implement automatic printing with background threads?

I'm developing a program that receives some data and after processing I want to print it.It should be automatic printing.The data is added as records to printList queue.Then a thread is supposed to print them one by one.here's the code :
private void button4_Click(object sender, EventArgs e)
{
rwl.AcquireWriterLock(10);
try
{
if (automaticPrint == false)
{
automaticPrint = true;
_automaticPrintThread = new Thread(new ThreadStart(AutomaticPrintA4));
_automaticPrintThread.IsBackground = true;
_automaticPrintThread.Start();
}
else
{
automaticPrint = false;
if (_automaticPrintThread != null)
{
_automaticPrintThread.Join(1);
}
}
}
finally
{
rwl.ReleaseWriterLock();
}
}
private void AutomaticPrintA4()
{
try
{
this.AutomaticPrintA4Delegate();
}
catch (Exception e)
{
this._automaticPrintThread.Abort();
MessageBox.Show(e.StackTrace);
}
}
private void AutomaticPrintA4Delegate()
{
try
{
if (this.InvokeRequired)
this.Invoke(new MethodInvoker(AutomaticPrintA4Delegate));
else
{
rwl.AcquireReaderLock(100);
Telerik.Reporting.Processing.ReportProcessor rp = new Telerik.Reporting.Processing.ReportProcessor();
System.Drawing.Printing.PrinterSettings ps = new System.Drawing.Printing.PrinterSettings();
try
{
while (automaticPrint)
{
rwlprintlist.AcquireReaderLock(10);
try
{
if (Session.printList != null)
{
if (Session.printList.Count != 0)
{
if (Session.printList[0] != null)
{
rp.PrintReport(new Report(Session.printList[0]), ps);
LockCookie lc = rwlprintlist.UpgradeToWriterLock(10);
Session.printList.RemoveAt(0);
rwlprintlist.DowngradeFromWriterLock(ref lc);
}
}
else
{
Thread.Sleep(1000);
}
}
else
{
Thread.Sleep(1000);
}
}
finally
{
rwlprintlist.ReleaseReaderLock();
}
}
}
finally
{
rwl.ReleaseReaderLock();
}
}
}
catch (Exception e)
{
MessageBox.Show("Print : " + e.StackTrace + e.Message);
}
}
A button click controls automaticprint variable.
rwl controls access to automatic print and rwlprintlist controls access to printList.
but my main gui hangs whenever I start this thread.I don't know why?
P.S. any other design ideas would be appreciated.
In your background worker you call AutomaticPrintA4Delegate. This method switches to the UI thread with
if (this.InvokeRequired)
this.Invoke(new MethodInvoker(AutomaticPrintA4Delegate));
So the print out is running in the UI thread and that is the reason, why your UI is "hanging".

Categories