Im fixing some errors in an existing C# project.
I use Visual Studio 2008 and 3.5 .NET Framework.
The application uses Forms, and the lifecycle of the application worked correctly. I didn't did any changes yet, but the client started experiencing strange behaviour lately.
The can use the app the first time without problems, but if a form is closed and we open another one, the objects in this form are Disposed.
The code is for a PDA, and we have a EventHandler for the Scan.
I belive this is very strange as nothing from the code has been changed.
Maybe it is some framework bug?
I've tried to completely eliminate the event handlers on the Closing event, but the same error happens.
Changing the way the forms are disposed.
Form creation
FormTEntreUbicaciones form = new FormTEntreUbicaciones(Movements.TREntreUbicaciones);
form.ShowDialog();
form.Dispose();
Event creation
if (Device.GetOSType2() == Device.OSType.WinMobile){
hDcd = new DecodeHandle(DecodeDeviceCap.Exists | DecodeDeviceCap.Barcode);
DecodeRequest reqType = (DecodeRequest)1 | DecodeRequest.PostRecurring;
dcdEvent = new DecodeEvent(hDcd, reqType, this);
dcdEvent.Scanned += new DecodeScanned(dcdEvent_Scanned);
}
The form should be open, and all the objects in it should NOT be disposed
Exception:
System.ObjectDisposedException was unhandled
Message="ObjectDisposedException"
ObjectName=""
StackTrace:
at System.Windows.Forms.Control.InvokeHelper(Delegate method, Boolean fSynchronous, Object[] rgobjArgs)
at System.Windows.Forms.Control.Invoke(Delegate method)
at Datalogic.API.DecodeEvent.WaitForScan()
Any suggestions?
Thanks!
Finally, I found a solution.
After figuring out what was going wrong, I found out that the SCAN event was kept alive.
I added a Closing override:
this.Closing += MyClosedHandler;
And the MyClosedHandlerEvent as follows:
//FIX MA 23.07.2019
protected void MyClosedHandler(object sender, EventArgs e)
{
if (dcdEvent.IsListening)
{
dcdEvent.StopScanListener();
}
if (hDcd != null)
{
hDcd.Dispose();
}
}
Problem was detected with datalogic.api.dll. The PDA used is the Skorpio x3.
Hope this will help somebody else!
Related
I'm having a bit of an issue that I'm stumped on and I was hoping someone could shed some light on it. I have a Form called form2 and I'm running some code to add some items to the Listview(s) of that form using a MethodInvoker so that the UI thread stays responsive while I do so.
Everything runs fine with it the first time around but then when I close that form (the one with the Listview on it) and run my code again I get a InvalidOperationException: Invoke or BeginInvoke cannot be called on a control until the window handle has been created.
So I looked into this and Googled it a bit more as well as looked on StackOverflow and I saw the issue was being caused by the form not having a handle created for it since it's being disposed when it's closed the first time.
So my solution was to have it force the form to set a handle for itself via CreateControl(). Even after using this, my form still isn't setting the handle when I inspect it in the break from the exception. It has 00x0000000 or something like that, and I'm still getting my InvalidOperationException. I have also tried to checked .isDisposed() and tried to use CreateControl() after that with no luck. Have any of you guys heard of this before? The other threads on SO have yield no solutions for me.
My Code:
if (!form2.IsHandleCreated)
{
form2.CreateControl();
}
form2.Invoke((MethodInvoker) delegate
{
//Do Stuff Here.
}
So since nobody responded to this I'll answer my own question in case anybody comes across this and it helps them. I actually ended up putting this outside the scope of my new thread that was created and creating the form in a button click event. I then checked to see if my form was Disposed or still open and created new instances of the Form based on that.
This is my code:
var checkDMS = CheckIfNull(dealtxt.Text);
if (checkDMS)
{
//If DMS Deal is valid -> If Form is Closed ->
if (form2.IsDisposed)
{
// If Form not open -> Create new instance
form2 = new Form2();
form2.Show();
form2.SendToBack();
}
else
{
// If Form still open -> Close and make new instance.
form2.Close();
form2 = new Form2();
form2.Show();
form2.SendToBack();
}
runDMSQueryFromNewThread(materialCheckBox1.Checked);
}
else
{
MessageBox.Show("Cannot Pull Deal From DMS.");
}
I am developing a webbrowser with Awesomium and I am using the newest version of it. However it has some issues when I dispose WebControls and when I shutdown the WebCore ( which also disposes the WebControls ).
Does anyone know a way around this? Thanks in advance
I have done a little bit of testing with this. I was trying to use the WPF version of WebControl and found that it can leak quite badly, especially when you are creating and destroying a lot of WebControls over time. So, I was fooling around with WindowsFormsHost and using the WinForms version of WebControl and even though it doesn't leak, I too was having the same issue you describe. It turns out you want to explicitly call Dispose AFTER the handle's to your window are cleaned up.
In WPF, I inherited WindowsFormsHost and specified an override to DestroyWindowCore like so:
protected override void DestroyWindowCore(System.Runtime.InteropServices.HandleRef hwnd) {
base.DestroyWindowCore(hwnd);// clean up handles
// Disposing here prevents access violation from crashing non-debug instances
// Confirmed to prevent access violation on WebCore shutdown as well
webControl1.Dispose();
webControl1 = null;
}
// This code seems to work in WinForms, I placed this in Form1.cs:
protected override void DestroyHandle() {
base.DestroyHandle();
webControl1.Dispose();
}
I would recommend playing around with different placements of where you dispose of the control. Typically after the host has released it's handles. I can confirm that I no longer have this issue and the Awesomium.Windows.Forms.WebControl is functioning properly on Dispose
Edit, I have uploaded my test project to DropBox here . The solution is for Visual Studio 2012 and targeting .net 4.5. Hope this helps!
I solved it by adding some code to the FormClosing event in my main form:
private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
{
foreach(WebControl awWebControl in WebCore.Views)
{
//Dispose all active views in WebCore
awWebControl.Dispose();
}
//then you can Shutdown the WebCore
WebCore.Shutdown();
}
Hope this helps
I have this weird and inconsistent issue.
The application is built in compact framework 3.5 running on a windows mobile 6.5 device.
The screen flow of the application is somewhat like this.
MainScreen (which is always running)
Screen1
Screen2
Screen3
MainsScreen -> Screen1 -> Screen2 -> Screen3 -> MainScreen
When the loop is completed and the application lands back on MainScreen, MainScreen.Activated() is called and on a condition launches automatically Screen1.
The code looks something like this:
private void MainScreen_Activated(object sender, EventArgs e)
{
if (Condition)
{
NextScreen();
return;
}
//other code here
}
private void NextScreen()
{
Screen1 formScreen1 = new Screen1 ();
formScreen1 .Show();
}
Screen1 has also this piece of code in the load of the form:
private void Screen1_Load(object sender, System.EventArgs e)
{
if(Condition)
{
NextScreen();
}
}
private void NextScreen()
{
Screen2 formScreen2= new Screen2();
formScreen2.Show();
Close();
}
So when this condition in Screen1_Load is fulfilled the application automatically launches Screen2 and closes this.
In this particular case it happens that sometimes a control on Screen2 gets disposed after the form is created. I know this because i can actually see the control for a split second on the screen.
The issue is also inconsistent, it won't happen all the time in the exact scenario which makes me believe it's got to something with bad timing.
The control that gets disposed seems to be also chosen at random, most of the times it's the same button but there were cases when a listbox from the form got disposed.
Please note that there is no code in the application that will call dispose of the control.
Any help is greatly appreciated. Thank you, hope i explained the issue well enough.
I found the cause and a solution to my issue.
After much investigation i found out that the button being disposed was coinciding with this chance exception happening in debug:
A first chance exception of type 'System.ObjectDisposedException' occurred in System.Drawing.dll
A first chance exception of type 'System.ObjectDisposedException' occurred in System.Drawing.dll
I also found out that this chance exception can happen when the device is or thinks it's running out of memory causing the GC to run and try to clear memory.
I used the answer to this question
Prevent Garbage Collector and also added GC.KeepAlive on the form that were suffering this issue.
The chance exception still happens in debug at the same time but i haven't been able to reproduce the issue since then.
my project a three tier architecture project talking to a WCF service in the backend. When the backend is able to fetch data from the service, it notifies the business layer using publish-subscribe, which in return notifies the GUI layer.
I have added an OpenFileDialog to my UI design using Visual Studios designer. A button event handler calls the ShowDialog message. However, once I click the button, the whole UI hangs.
Having googled around a bit, I found out that using delegates is the preferred way to handle tasks like this. However, with nor without delegate the problem persists.
Currently my code looks like this:
private void bOpen_Click(object sender, EventArgs e)
{
Func<Image> del = delegate
{
OpenFileDialog d = new OpenFileDialog();
if (d.ShowDialog() == DialogResult.OK)
{
return Image.FromFile(d.FileName);
}
return null;
};
Invoke(del);
}
I'm coming from the Java world, so I'm not really familiar with the intricacies of C# UI programming.
Anything I'm missing here?
openFileDialog1->ShowHelp = true;
I put this line in my code then the problem was solved.
I seem to have solved the problem adding the [STAThread] Attribute to the main method. I was told to do so once I ran the program in a debugger - which I hadn't done before because I ran the service from Visual Studio and the client regularly from Windows.
[STAThread]
public static void Main(string[] args)
{
GUI gui = new GUI();
gui.ShowDialog();
}
Can anybody explain what exactly is going on though
This tends to be an environmental problem, when you use OpenFileDialog a lot of shell extensions get loaded into your process. A misbehaving one can easily screw up your program. There are a lot of bad ones out there.
Debugging this is difficult, you need an unmanaged debugger since these shell extensions are unmanaged code. You might be able to tell something from the call stack when you break in after the deadlock. Windows debugging symbols required, enable the Microsoft symbol server. But the most effective approach is to use SysInternals' AutoRuns utility. Start by disabling all of the shell extensions that were not produced by Microsoft. Then start re-enabling the ones you cannot live without one by one.
And, as you found out, these shell extension expect to run on an STA thread and fail miserably when they don't get it. The UI thread of a program must always be STA, also to support the clipboard and drag-and-drop and various kinds of controls like WebBrowser. Normally always taken care of automatically by the [STAThread] attribute on the Main() method, put there by the project template. And the Application.Run() call, required to implement the STA contract. Deadlock when you don't.
I believe the "delegate" prefered way actually refers to using a separate thread.
I'm gonna give you an example using BackgroundWorker.
It would look like this:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
m_Worker.DoWork += new DoWorkEventHandler(m_Worker_DoWork);
m_Worker.ProgressChanged += new ProgressChangedEventHandler(m_Worker_ProgressChanged);
m_Worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(m_Worker_RunWorkerCompleted);
}
void m_Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//Usually, used to update a progress bar
}
void m_Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//Usually, used to add some code to notify the user that the job is done.
}
void m_Worker_DoWork(object sender, DoWorkEventArgs e)
{
//e.Argument.ToString() contains the path to the file
//Do what you want with the file returned.
}
private void bOpen_Click(object sender, EventArgs e)
{
OpenFileDialog d = new OpenFileDialog();
if (d.ShowDialog() == DialogResult.OK)
{
m_Worker.RunWorkerAsync(d.FileName);
}
}
BackgroundWorker m_Worker = new BackgroundWorker();
}
Now, as for the reason your UI "hangs", it's because by default, your operation runs on the UI thread, so if you run something heavy the UI won't respond.
I also met this problem. And I tried all the solution here and none can solve it. Then I change the target framework from .Net Framework 4.7 to 4.6.2, the problem solved...
I think my problem is different, as none of the above solutions worked for me.
I wrote temporary code to set the OpenFileDialog.FileName property to something not null or empty string (it was empty string when the hang up occured), and I restarted my computer. When I started up Visual Studio again, and ran it, it worked again without hanging up.
I am using Wndows XP SP3 x86 + VSTS 2008 to write a simple Windows Forms application using C#. There is a button called button1 and here is the event handler for its click event, when executing the if statement, there is Microsoft.VisualStudio.Debugger.Runtime.CrossThreadMessagingException. Does anyone have any good ideas what is wrong?
private void button1_Click(object sender, EventArgs e)
{
string recording = ConfigurationSettings.AppSettings["recording"];
// exception thrown when executing the following if statement
if (recording.Equals("enable", StringComparison.InvariantCultureIgnoreCase))
{
CameraEncoder.Stop();
}
}
Some more code:
static WMEncoder CameraEncoder = new WMEncoder();
EDIT1:
I am confused how to apply Marc's idea of using Invoke in my code. Should I use the following code segment?
CameraEncoder.Invoke((MethodInvoker) delegate
{
CameraEncoder.Stop();
});
Normally, the problem when we see this (regularly) is something like a worker thread or a timer updating the UI - but a button click should be raised through the UI thread, so I don't think it is the "usual problem".
So: what is camera? And what is Recording? Neither is explained, and we can't guess without introducing extra variables...
Depending on what they are, maybe this'll work...
camera.Invoke((MethodInvoker) delegate
{
if (camera.Equals("enable", StringComparison.InvariantCultureIgnoreCase))
{
Recording.Stop();
}
});
But without knowing what canera is, I'm clutching at straws...
Maybe the camera object is created and managed by another thread.. Could you expose more code regarding the camera object?
I know WMEncoder is a COM object. You might try creating CameraEncoder in the GUI thread instead of a different thread.