Im trying to call some windows forms code (like setting label.visible = true in some event code, everything compiles ok, but form does not react to change! What could be the problem?
Problem is in lines:
labelNewCall.Visible = true;
timerNewCall.Enabled = true;
code : http://pastebin.com/gV28PN4P
also other code did not work, until i reordered some of it (order is not important but it did not work otherwise... )
You can also try a handy little method that you can place in your inner-loop:
Application.DoEvents();
Here's the MSDN write up:
http://msdn.microsoft.com/en-us/library/system.windows.forms.application.doevents.aspx
Do you call this method in another than UI thread? If so, you should use Invoke and/or BeginInvoke method.
Look at article What's up with BeginInvoke?.
This could be because the soundCapture_BufferThrown callback function is not run on the GUI thread. Read this post for more details about threading in WinForms.
Use invoke to access object in a windows forms/controls thread
Reference - http://www.dailycoding.com/...formscontrols_thread.aspx
Related
Recently we came across some legacy WinForms application we needed to update with some new features. While expert testing the application, it was found that some old functionality is broken. Invalid cross-thread operation. Now before you take me for a newbie, I do have some experience with Windows Forms applications. I'm no expert, but I consider myself experienced with threading and know exactly how to manipulate GUI components from a worker thread.
Apparently the one who wrote this piece of software did not and just set UI control properties from a background thread. Of course it threw the usual exception, but it was encased in an all-catching try-catch block.
I spoke with a stakeholder to find out how long this functionality had been broken, and turned out it was fine before. I couldn't believe that, but he demoed me that the function actually works in PROD.
So our unrelated updates "broke" the software in three places, but I can't get my head around how it could have worked in the first place. According to source control, the bug has always been there.
Of course we updated the application with proper cross-thread UI handling logic, but now I'm in the unlucky position of having to explain to stakeholders with not much tech background why something that can't have worked like ever, did work fine until we did some unrelated changes to the system.
Any insights would be appreciated.
One more thing that came to mind: in two of the cases the background thread updated a ListView control that was on a non-selected (and thus non-displayed) TabPage control. The third time it was standard Label control (text property was set) that was initially empty and gets a Text assigned according to what the background thread finds.
Here's some code for you, very similar to the one we found:
private void form_Load(object sender, System.EventArgs e)
{
// unrelated stuff...
ThreadStart ts = new ThreadStart(this.doWork);
Thread oThread = new Thread(ts);
ts.Start();
// more unrelated stuff ...
}
public void doWork()
{
string error = string.Empty;
int result = 0;
try
{
result = this.service.WhatsTheStatus(out error); // lengthy operation
switch (result)
{
case 1:
this.lblStatus.Text = "OK";
break;
case -1:
this.lblStatus.Text = "Error";
this.lblError.Text = error;
break;
default:
this.lblStatus.Text = "Unknown";
break;
}
}
catch
{
}
}
Unfortunately I saw lblStatus being updated in the production environment and it isn't referenced from anywhere else in the entire application (except the Designer generated stuff, of course).
That is because cross-thread access exceptions are not guaranteed to be thrown when you run code without debugger (in windows forms). Read this for example: https://msdn.microsoft.com/en-us/library/vstudio/ms171728%28v=vs.110%29.aspx:
The .NET Framework helps you detect when you are accessing your controls in a manner that is not thread safe. When you are running your application in the debugger, and a thread other than the one which created a control tries to call that control, the debugger raises an InvalidOperationException with the message, "Control control name accessed from a thread other than the thread it was created on."
This exception occurs reliably during debugging and, under some circumstances, at run time. You might see this exception when you debug applications that you wrote with the .NET Framework prior to the .NET Framework 2.0. You are strongly advised to fix this problem when you see it, but you can disable it by setting the CheckForIllegalCrossThreadCalls property to false. This causes your control to run like it would run under Visual Studio .NET 2003 and the .NET Framework 1.1.
You can check this yourself by writing simple winforms application, set form title from another thread and see exception is thrown. Then run same application without debugger attach and see how form title will happily change without any problems.
I have a silverlight application. When some action is executed, i want to show a wait cursor.
The problem is that i'm working with threads, and all my actions are executed in a thread.
So i have a threading helper that invokes and awaits all the threads - this works fine.
I need to access the main window element to change its cursor. How can i achieve this?
This:
ThreadingHelper.Invoke(() => App.Current.MainWindow.Content.Cursor = cursorStyle);
Throws me System.NotSupportedException: Out-of-browser specific settings do not affect in-browser applications.
How can i do the same for In-browser?
I have managed to get this working by this code:
ThreadingHelper.Invoke(() => {
var page = (MainPage)Application.Current.RootVisual;
page.Cursor = cursorStyle;
});
But maybe someone will offer more type-safe method?
I m getting an error in WP 7.1 like below
InvalidOperationException
"Navigation is not allowed when the task is not in the foreground"
In the following line of code
NavigationService.Navigate(new Uri("/PhotoPreview.xaml", UriKind.Relative));
I dont have any clue how to solve it. It would be great if you can provide some pointers
If you need to call it from the main UI thread, use this:
Dispatcher.BeginInvoke(() =>
{
NavigationService.Navigate(new Uri("/PhotoPreview.xaml", UriKind.Relative));
});
While using Dispatcher.BeginInvoke may help, it may well not fix your issue. I've also seen this occur if there is a race condition between 2 conflicting navigations, e.g. back key and forward navigation, or 2 forward navigations. See discussion on App Hub.
I'm reading between the lines here and assuming that you are using either the CameraCaptureTask or PhotoChooserTask due to the navigation string you are using "/PhotoPreview.xaml".
After battling with this issue myself I found that not only do you need to ensure that the navigation is called on the UI thread ( by using Dispatcher.BeginInvoke() ) but the CameraCaptureTask object must be declared with class scope within the PhoneApplicationPage class and you must call the chooser constructor and assign the Completed event delegate within the page’s constructor.
private readonly CameraCaptureTask cameraCaptureTask;
public MainPage()
{
cameraCaptureTask = new CameraCaptureTask();
cameraCaptureTask.Completed += CameraCaptureCompleted;
}
otherwise your application will be deactivated in the background and will never recieve the photo. Causing the application to crash with one of the following exceptions:
Navigation is not allowed when the task is not in the foreground
0x8000ffff
Navigation is not allowed after the task has been
canceled. Error: -2147220992
Navigation is not allowed when the task
is not in the foreground. Error: -2147220990
Some further tips:
Don't remove the event handler in your CameraCaptureCompleted method either or it won't work the next time around!
You may also want to add some code to ensure that navigation can't occur twice due to multiple button clicks for example; the touch screens can be quite sensitive! If you are only using the capture task, a try catch block around the Show() call to trap an InvalidOperationException should be fine.
tl;dr
Only assign the CameraCaptureTask/PhotoChooser and it's event handler in your page constructor.
i've wrote a API in C# which will be used in vb6 & vbscript and assume my API details is as below:
1. there is a form in the API but it is not exposed to COM
2. there is a method called ShowForm() with code "form1.Show()". This method ShowForm() is exposed to COM so that i can call this method from vb6/vbscript.
So, my problem is:
When i call ShowForm() method in vb6 under a button click event, the form created in C# API shows up but if i instantiate the same class and call the same method in vbscript, the form dont show up.
However, if i change the code in ShowForm(),
- from "form1.Show()" to "form1.ShowDialog()", it will show in both vb6/vbscript. But, it is showed as a modal form where what i want is modeless
OR
- from "form1.Show()" to "Application.Run(form1)". It will shows up in vbscript but not in vb6 (it actually shows up in vb6, but it crash after i close the form in C#)
What can i do to make it works fine in vb6 and vbscript? Your advice is very much appreciated
PS: its not script syntax problem or COM problem. it should be something to do with form.show()/ShowDialog()/Application.Run() or message loop thingy which is something i dont really understand
My code would be more or less something like this.
//C# code
public void ShowForm()
{
m_frm.tempWebBrowser.Navigate("http://stackoverflow.com", "_self", Encoding.Default.GetBytes(""), "Content-Type: application/x-www-form-urlencoded");
m_frm.FormBorderStyle = FormBorderStyle.Sizable;
m_frm.ShowInTaskbar = true;
m_frm.WindowState = FormWindowState.Maximized;
m_frm.tempWebBrowser.Visible = true;
m_frm.Show();
}
//VB6 code, vbscript also using exactly the same code in the event
Private Sub Command1_Click()
Dim tempClass
Set tempClass = CreateObject("myClass.API")
tempClass.ShowForm
End Sub
The form is not shown exactly because of what you suggested...there is no message pump running on the thread. If you are trying to fire-and-forget the C# window from VBScript, I suggest you launch it in a seperate process. It would have the same effect as you've described. If you instead were trying to launch it and wait for the user to interact with it (say you are prompting them for info) then showing to form modally is appropriate.
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.