Running the really simple program below I'd expect 'FILTER REACHED' to execute when I click button1, but it doesn't get hit (neither with nor without debugger attached). Any ideas ... ?
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
new Thread(() =>
{
Dispatcher.CurrentDispatcher.UnhandledExceptionFilter += Dispatcher_UnhandledExceptionFilter;
doer();
}).Start();
}
void Dispatcher_UnhandledExceptionFilter(
object sender,
DispatcherUnhandledExceptionFilterEventArgs e)
{
MessageBox.Show("FILTER REACHED");
}
private void doer()
{
throw new NotImplementedException();
}
}
Thanks
According to the documentation on Dispatcher (found here) it looks like the filter function will only be used if an uncaught exception is raised from the Invoke or BeginInvoke methods on the Dispatcher.
So what happens if you replace doer() with Dispatcher.CurrentDispatcher.Invoke(doer) (or similar) instead?
You are calling the method (doer) from a thread which is not the dispatcher thread.. you have to invoke the method using Dispatcher in order to catch the exception for filtering.
new Thread(() =>
{
Dispatcher.CurrentDispatcher.UnhandledExceptionFilter += Dispatcher_UnhandledExceptionFilter;
Dispatcher.Invoke(new Action(()=>doer()));
}).Start();
try below code
new Thread(() =>
{
Dispatcher.CurrentDispatcher.UnhandledExceptionFilter += Dispatcher_UnhandledExceptionFilter;
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Normal, new ThreadStart(delegate
{
doer();
}));
}).Start();
Have you tried using AppDomain.UnhandledException instead?
Related
My constructor besides other things call another method DoWork
public MyTask(TaskAction action)
{
DoWork(action);
}
DoWork method goes to another method Calc(2)
private void Calc (int 2){
... calc and save result into file
}
How can I alert MyTask that Calc is done and let MyTask to continue further.
P.S. I could read hdd every few secs in order to see whether file with result is save and based on that continue further, but I assume that there is better way.
BackgroundWorker class allows you to easily manage your async work.
BackgroundWorker _worker = new BackgroundWorker();
public Cnt()
{
InitializeComponent();
_worker.DoWork += WorkerOnDoWork;
_worker.RunWorkerCompleted += WorkerOnRunWorkerCompleted;
//start your work
_worker.RunWorkerAsync();
}
private void WorkerOnRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//Worker completed event
}
private void WorkerOnDoWork(object sender, DoWorkEventArgs e)
{
//Do
}
There are many ways to do this.The latest recommended is using tasks
Task taskA = new Task(() => { Console.WriteLine("Task A started"); });
taskA.ContinueWith((ss) => { Console.WriteLine("Task A finished"); });
taskA.Start();
http://msdn.microsoft.com/en-us/library/ee372288(v=vs.110).aspx
This way you can block the current thread if you want.
Another way is the BackGroundWorker Class
Also, you can use a custom callback like this
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
DoWorkA(DoWorkFinished);
Console.Read();
}
private static void DoWorkA(Action whatToDoWhenFinished)
{
Console.WriteLine("Doing something");
whatToDoWhenFinished();
}
private static void DoWorkFinished()
{
Console.WriteLine("Doing something Else");
}
}
}
I am running the following line to get a list of all services for a given computer:
ServiceController[] services = ServiceController.GetServices(compName);
If I run this on the main thread and pass in a computer name that exists but I don't have permissions to view the services for, such as:
ServiceController.GetServices("OtherComp");
InvalidOperationException:
Cannot open Service Control Manager on computer 'OtherComp'. This operation might require other privileges.
I fully expect this to happen. However my issue comes with running this on a background thread. Take this fully complete console program:
using System.ComponentModel;
using System.ServiceProcess;
namespace ServiceTesting
{
internal class Program
{
private static void Main(string[] args)
{
ServiceAccessor sa = new ServiceAccessor();
sa.Run();
}
}
public class ServiceAccessor
{
BackgroundWorker bw;
public ServiceAccessor()
{
bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted += new
RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
}
public void Run()
{
bw.RunWorkerAsync();
}
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
//this line is where the bail happens
var services = ServiceController.GetServices("OtherComputer");
}
void bw_RunWorkerCompleted(object sender,RunWorkerCompletedEventArgs e)
{
// the code will never get to this method
if (e.Error != null)
{
//something
}
}
}
}
I would expect an exception to be thrown, but as soon as the code tries to execute this line, it bails out of the thread.
I can't wrap the line in a try\catch; it will won't catch it. This might be simmilar to ThreadAbort problems with asp.net (but that is just a guess).
The msdn page on the ServiceController Class says that the static function is thread safe, however, a commenter on the function's msdn page says that it is not.
Exception was catched by BackgroundWorker internally, you can view it via RunWorkerCompleted event:
private void backgroundWorker1_RunWorkerCompleted(
object sender, RunWorkerCompletedEventArgs e)
{
// First, handle the case where an exception was thrown.
if (e.Error != null)
{
// deal with error
}
}
http://msdn.microsoft.com/en-us/library/system.componentmodel.runworkercompletedeventargs.aspx
UPD: However, it works as expected with Thread class:
new Thread(() =>
{
try
{
var services = ServiceController.GetServices("OtherComputer");
}
catch
{
}
}).Start();
I have been searching for an answer to my particular problem for a while with no success.
I have a task in my program that takes a few seconds and I want to show a new form while that task is being done. The new form has a loadingbar and some text.
I need to show the new form parallel to the task otherwise the task will not start untill I close the new form.
This is the solution I have now:
private void loadingBar()
{
frmLoading frm = new frmLoading("Please wait while the database is being backed up", "This might take several days.");
frm.ShowDialog();
}
public void Backup()
{
Thread load = new Thread(new ThreadStart(loadingBar));
load.Start();
///Execute a task.
load.Abort();
}
So, this works OK but my question is: Wouldn't it be better to close the the form "frm" in the load-thread to make it stop?
You could do this a few ways...
1 - You could do as BendEg suggested and invoke you frmClose once you are ready
Something like;
Invoke(new Action(Close));
or
Invoke(new Action(() => frmMain.Close()));
2 - Or you could simply use a background worker;
The simplest way to demonstrate this would be to add a BackgroundWorker to your form, and use the events provided;
public Form1()
{
InitializeComponent();
backgroundWorker1.RunWorkerAsync();
MessageBox.Show(#"Please wait while the database is being backed up", #"This might take several days.");
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
Debug.WriteLine("Running"); //Execute a task
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Debug.WriteLine("Ended"); //Dispose of any objects you'd like (close yor form etc.)
}
I hope this helps.
You can declare the form on Class-Level and later close it with an invoke.
MSDN-Windows Forms Invoke
Like this:
public class Class1
{
private Form myForm;
public Class1()
{
myForm = new Form();
}
public void DoSomeWork()
{
// ===================================================
// Do Some Work...
// ===================================================
myForm.Invoke(new MethodInvoker(this.Hide));
}
public void Hide()
{
myForm.Hide();
}
public void Backup()
{
myForm.ShowDialog();
Thread load = new Thread(new ThreadStart(DoSomeWork));
load.Start();
}
}
I think this can work for you.
void YourMethod()
{
WaitForm wf = new WaitForm();
Invoke(new PleaseWaitDelegate(Launch),wf);
bool val = BoolMethodDoWork();
Invoke(new PleaseWaitDelegate(Close), wf);
if(val)
{
MessageBox.Show("Success!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
return;
}
MessageBox.Show("Damn!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
}
delegate void PleaseWaitDelegate(Form form);
void Launch(Form form)
{
new System.Threading.Thread(()=> form. ShowDialog()).Start();
}
void Close(Form form)
{
form.Close();
}
I think this will help you (if i understood you right):
Parallel.Invoke(() => somemethod(), () =>
{
someothertaskmethod();
});
I placed methods as example to demonstrate 2 tasks running.
You nee to use the proper using statement using System.Threading.Tasks;
Consider the following code for a WPF ViewModel:
protected void Init()
{
Debug.WriteLine(string.Format("ChangeManager init on thread={0}", Thread.CurrentThread.ManagedThreadId));
var uiTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
this.modelChanged = (o, args) => Task.Factory.StartNew(() =>
{
Debug.WriteLine(string.Format("ModelChanged on thread={0}", Thread.CurrentThread.ManagedThreadId));
this.ModelChanged(o, args);
},
CancellationToken.None,
TaskCreationOptions.None,
uiTaskScheduler);
}
... where modelChanged is an event handler for responding to changes in an object model. This code executes on the UI thread and is designed in hopes of having events handled on the UI thread regardless of which thread they are fired from.
However, when this gets run the output is something similar to:
ChangeManager init on thread=1
ModelChanged on thread=3
ModelChanged on thread=3
ModelChanged on thread=7
ModelChanged on thread=9
My expectation would be that thread 1 would be where all handling would take place. Even when I try using the SynchronizationContext directly like this:
protected void Init()
{
Debug.WriteLine(string.Format("ChangeManager init on thread={0}", Thread.CurrentThread.ManagedThreadId));
this.uiContext = SynchronizationContext.Current;
modelChanged = (o, args) => uiContext.Post((ignore) => {
Debug.WriteLine(string.Format("ModelChanged on thread={0}", Thread.CurrentThread.ManagedThreadId));
this.ModelChanged(o, args);
}
, null);
}
... I see the same thing.
Is there something wrong with my thinking or approach? How do I get the events to be handled on the init thread?
Thanks in advance!
Interesting, your code works for me. Maybe you left out parts of the code that can explain the problem. Can you post a more complete reproduction of the problem? And specifically, show what you are doing with the modelChanged member other than assigning the lambda to it.
What I did was, create an empty WPF application and run your Init method from the main window's constructor.
Then I started background threads that called the modelChanged delegate directly.
What I saw was that the line "ModelChanged on thread..." always printed the correct thread, the one which called Init.
If it's any help, here's what I did to try to reproduce it, you can look at it and maybe post about what you're doing differently:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Init();
}
private EventHandler modelChanged;
protected void Init()
{
Trace.WriteLine(string.Format("ChangeManager init on thread={0}",
Thread.CurrentThread.ManagedThreadId));
var uiTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
modelChanged = (o, args) => Task.Factory.StartNew(() =>
{
Trace.WriteLine(string.Format("ModelChanged on thread={0}",
Thread.CurrentThread.ManagedThreadId));
if (ModelChanged != null)
{
ModelChanged(o, args);
}
},
CancellationToken.None,
TaskCreationOptions.None,
uiTaskScheduler);
}
public event EventHandler ModelChanged;
private void button1_Click(object sender, RoutedEventArgs e)
{
var t = new Thread(
obj =>
{
Trace.WriteLine(string.Format(
"Launching handler on thread={0}",
Thread.CurrentThread.ManagedThreadId));
modelChanged(null, EventArgs.Empty);
});
t.Start();
}
}
Looks like in your case Init() isn't running on the UI thread. To make sure something runs on the UI thread, you can use some control's (e.g. Window's) Dispatcher property, and use it to run code on the UI thread like so:
someControl.Dispatcher.Invoke(() => { /* do something with the UI */ });
This specific overload of Invoke() is an extension method that requires a reference to System.Windows.Presentation.dll and a using System.Windows.Threading; directive, and requires .NET 3.5 SP1 and above.
When you subscribe to an event on an object from within a form, you are essentially handing over control of your callback method to the event source. You have no idea whether that event source will choose to trigger the event on a different thread.
The problem is that when the callback is invoked, you cannot assume that you can make update controls on your form because sometimes those controls will throw an exception if the event callback was called on a thread different than the thread the form was run on.
To simplify Simon's code a bit, you could use the built in generic Action delegate. It saves peppering your code with a bunch of delegate types you don't really need. Also, in .NET 3.5 they added a params parameter to the Invoke method so you don't have to define a temporary array.
void SomethingHappened(object sender, EventArgs ea)
{
if (InvokeRequired)
{
Invoke(new Action<object, EventArgs>(SomethingHappened), sender, ea);
return;
}
textBox1.Text = "Something happened";
}
Here are the salient points:
You can't make UI control calls from a different thread than the one they were created on (the form's thread).
Delegate invocations (ie, event hooks) are triggered on the same thread as the object that is firing the event.
So, if you have a separate "engine" thread doing some work and have some UI watching for state changes which can be reflected in the UI (such as a progress bar or whatever), you have a problem. The engine fire's an object changed event which has been hooked by the Form. But the callback delegate that the Form registered with the engine gets called on the engine's thread… not on the Form's thread. And so you can't update any controls from that callback. Doh!
BeginInvoke comes to the rescue. Just use this simple coding model in all your callback methods and you can be sure that things are going to be okay:
private delegate void EventArgsDelegate(object sender, EventArgs ea);
void SomethingHappened(object sender, EventArgs ea)
{
//
// Make sure this callback is on the correct thread
//
if (this.InvokeRequired)
{
this.Invoke(new EventArgsDelegate(SomethingHappened), new object[] { sender, ea });
return;
}
//
// Do something with the event such as update a control
//
textBox1.Text = "Something happened";
}
It's quite simple really.
Use InvokeRequired to find out if this callback happened on the correct thread.
If not, then reinvoke the callback on the correct thread with the same parameters. You can reinvoke a method by using the Invoke (blocking) or BeginInvoke (non-blocking) methods.
The next time the function is called, InvokeRequired returns false because we are now on the correct thread and everybody is happy.
This is a very compact way of addressing this problem and making your Forms safe from multi-threaded event callbacks.
I use anonymous methods a lot in this scenario:
void SomethingHappened(object sender, EventArgs ea)
{
MethodInvoker del = delegate{ textBox1.Text = "Something happened"; };
InvokeRequired ? Invoke( del ) : del();
}
I'm a bit late to this topic, but you might want to take a look at the Event-Based Asynchronous Pattern. When implemented properly, it guarantees that events are always raised from the UI thread.
Here's a brief example that only allows one concurrent invocation; supporting multiple invocations/events requires a little bit more plumbing.
using System;
using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public class MainForm : Form
{
private TypeWithAsync _type;
[STAThread()]
public static void Main()
{
Application.EnableVisualStyles();
Application.Run(new MainForm());
}
public MainForm()
{
_type = new TypeWithAsync();
_type.DoSomethingCompleted += DoSomethingCompleted;
var panel = new FlowLayoutPanel() { Dock = DockStyle.Fill };
var btn = new Button() { Text = "Synchronous" };
btn.Click += SyncClick;
panel.Controls.Add(btn);
btn = new Button { Text = "Asynchronous" };
btn.Click += AsyncClick;
panel.Controls.Add(btn);
Controls.Add(panel);
}
private void SyncClick(object sender, EventArgs e)
{
int value = _type.DoSomething();
MessageBox.Show(string.Format("DoSomething() returned {0}.", value));
}
private void AsyncClick(object sender, EventArgs e)
{
_type.DoSomethingAsync();
}
private void DoSomethingCompleted(object sender, DoSomethingCompletedEventArgs e)
{
MessageBox.Show(string.Format("DoSomethingAsync() returned {0}.", e.Value));
}
}
class TypeWithAsync
{
private AsyncOperation _operation;
// synchronous version of method
public int DoSomething()
{
Thread.Sleep(5000);
return 27;
}
// async version of method
public void DoSomethingAsync()
{
if (_operation != null)
{
throw new InvalidOperationException("An async operation is already running.");
}
_operation = AsyncOperationManager.CreateOperation(null);
ThreadPool.QueueUserWorkItem(DoSomethingAsyncCore);
}
// wrapper used by async method to call sync version of method, matches WaitCallback so it
// can be queued by the thread pool
private void DoSomethingAsyncCore(object state)
{
int returnValue = DoSomething();
var e = new DoSomethingCompletedEventArgs(returnValue);
_operation.PostOperationCompleted(RaiseDoSomethingCompleted, e);
}
// wrapper used so async method can raise the event; matches SendOrPostCallback
private void RaiseDoSomethingCompleted(object args)
{
OnDoSomethingCompleted((DoSomethingCompletedEventArgs)args);
}
private void OnDoSomethingCompleted(DoSomethingCompletedEventArgs e)
{
var handler = DoSomethingCompleted;
if (handler != null) { handler(this, e); }
}
public EventHandler<DoSomethingCompletedEventArgs> DoSomethingCompleted;
}
public class DoSomethingCompletedEventArgs : EventArgs
{
private int _value;
public DoSomethingCompletedEventArgs(int value)
: base()
{
_value = value;
}
public int Value
{
get { return _value; }
}
}
}
As the lazy programmer, I have a very lazy method of doing this.
What I do is simply this.
private void DoInvoke(MethodInvoker del) {
if (InvokeRequired) {
Invoke(del);
} else {
del();
}
}
//example of how to call it
private void tUpdateLabel(ToolStripStatusLabel lbl, String val) {
DoInvoke(delegate { lbl.Text = val; });
}
You could inline the DoInvoke inside your function or hide it within separate function to do the dirty work for you.
Just keep in mind you can pass functions directly into the DoInvoke method.
private void directPass() {
DoInvoke(this.directInvoke);
}
private void directInvoke() {
textLabel.Text = "Directly passed.";
}
In many simple cases, you can use the MethodInvoker delegate and avoid the need to create your own delegate type.