How to make sure that a thread is awaiting for events? - c#

I wonder how to make sure that a thread is awaiting for events.
Let say I've a component that raises events:
public delegate void TestHandler(object sender, EventArgs eventArgs);
class Producer
{
public event TestHandler Handler;
public void InvokeHandler(EventArgs eventargs)
{
var handler = Handler;
if (handler != null) handler(this, eventargs);
}
public Producer()
{
Task.Factory.StartNew(() =>
{
while (true)
{
Thread.Sleep( (new Random()).Next(0,100) );
InvokeHandler(new EventArgs());
} }); } }
And a Listener:
class Listener
{
private readonly BlockingCollection<EventArgs> _blockingCollection;
public Listener()
{
var producer = new Producer();
_blockingCollection = new BlockingCollection<EventArgs>(10);
producer.Handler += producer_Handler;
}
void producer_Handler(object sender, EventArgs eventArgs)
{
_blockingCollection.TryAdd(eventArgs); //no error handling for simplicity sake
}
internal void ProcessEvents()
{
while (true)
{
EventArgs eventArgs;
try
{
if (_blockingCollection.TryTake(out eventArgs))
Console.WriteLine("Received event");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
} } } }
If I would start it as:
class Program
{
static void Main(string[] args)
{
var listner = new Listener();
listner.ProcessEvents();
} }
I got expected behaviour (from time to time I'm getting the event through blocking collection.
However if I would wrap this call in Task:
Task.Factory.StartNew(() => {
var listner = new Listener();
listner.ProcessEvents(); });
I will never got into the processing part.
Any idea why it would be? Do I miss something obvious?
On the side, does someone know a good description of a pattern that will help here?
I'm looking to pick-up events on one thread (preferably not the main application thread), then process them on a separate thread at the same time blocking if the number of events is getting too high (typical thresholdingI assume)
Thanks in advance,

Stupid me...
When I wrap my call in Task it is run on a Background thread.
I should have wait for the task to finish before quiting.
Having done that, that is assigning:
var task = Task.Factory.StartNew(/*task body*/);
task.Wait();
and waiting I have got what I want.

In order to figure out what's going on you should put some logging messages and verify that no exceptions are thrown when when you start the new task:
Thread listenerThread = new Thread(() =>
{
// print a message when the task is started
Console.WriteLine("Task started!");
var listner = new Listener();
listner.ProcessEvents();
});
// set your thread to background so it doesn't live on
// even after you're
listenerThread.IsBackground = true;
listenerThread.Start();
Thread.Join() does the same thing as Task.Wait(). You can call it without specifying a timeout, you can specify an infinite timeout or if you want your test to stop waiting for the thread to finish, then you specify a timeout in milliseconds:
// this will block until the thread is complete
listenerThread.Join(Timeout.Infinite);
If you need to stop the test, then you have to perform an asynchronous interrupt. Interrupt raises a ThreadInterruptedException inside the Thread which you're supposed to catch (as shown in the ProcessEvents method):
listenerThread.Interrupt();
Additionally, you're using a blocking collection, but you're not utilizing the blocking functionality of the collection. There is no reason why you should keep retrying when there is nothing in the collection, instead you would rather block until there is something in it (which is what this collection is designed to do):
internal void ProcessEvents()
{
while (true)
{
try
{
var myEvent = _blockingCollection.Take();
Console.WriteLine("Received event");
}
catch(ThreadInterruptedException)
{
Console.WriteLine("Thread interrupted!");
break;// break out of the loop!
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
// Do you REALLY want to keep going if there is an unexpected exception?
// Consider breaking out of the loop...
}
}
}

Related

C# .NET 5.0 Wpf UI modified by another thread

I'm having some trouble in updating a WPF UI from another Thread.
The second Thread is a loop that constantly read messages from a StreamReader.
In these messages there are commands that update the UI.
I have no idea how to do. I read articles about similar problems but were not the same
WPF interface:
private void Button_Click(object sender, RoutedEventArgs e)
{
Thread threadConsume = new Thread(pre_sub);
threadConsume.Start();
}
Other thread:
private void pre_sub()
{
Subscribe();
}
public async Task Subscribe()
{
while (true)
{
try
{
Console.WriteLine("Establishing connection");
using (var streamReader = new StreamReader(await _client.GetStreamAsync(_urlSubscription)))
{
while (!streamReader.EndOfStream)
{
var stream = await streamReader.ReadLineAsync();
if (stream.ToString() == "update")
{
//update the WPF UI
}
}
}
}
catch (Exception ex)
{
}
}
}
Do not create a Thread when you already make async calls.
Simply call and await the async method in an async event handler. The UI updates would thus be made in the UI thread. No Dispatcher calls would be necessary.
private async void Button_Click(object sender, RoutedEventArgs e)
{
await Subscribe();
}
Besides that, you would obviously need some mechanism that stops the infinite loop in the Subscribe method.
You need to use BeginInvoke method. Something in the line of:
.....
while (!streamReader.EndOfStream)
{
var stream = await streamReader.ReadLineAsync();
if (stream.ToString() == "update")
{
var dispatcher = Application.Current.MainWindow.Dispatcher;
dispatcher.BeginInvoke(new Action(() =>
{
//update the WPF UI
}), (DispatcherPriority)10);
}
}
break; ///if UI Updated exit the while true loop
.....
Also, as a side note, don't every swallow exceptions. Log or/and handle the exception on catch block
You have to call dispatcher in order to update the UI
Dispatcher.BeginInvoke(() =>
{
//Update the UI
});

C# Using block with an anonymous method referencing the IDisposable object

Consider the following code:
using (var mre = new ManualResetEvent(false))
{
var bgWkr = new BackgroundWorker();
bgWkr.DoWork += delegate(object sender, DoWorkEventArgs e)
{
var mrEvent = e.Argument as ManualResetEvent;
// some processing...
mrEvent.WaitOne();
// broadcast an event
};
bgWkr.RunWorkerAsync(mre);
// some other processing...
// hook into the same event
mre.Set();
}
Let's say that the spawned worker takes a bit of time to complete. We will have left the using block a while ago by the time the worker thread finishes and waits on the ManualResetEvent. I would assume that the mre would have been closed when leaving the using block (given that it would have been disposed) and this would throw an exception at the very least. Is this a safe assumption to make?
This example may not be the best one with the ManualResetEvent but it is to illustrate the case where we access an IDisposable object inside an anonymous method within a using block and the anonymous method is called after we have exited the using block. Is there some mechanism that keeps hold of the disposable object? I don't believe so but would like some confirmation as to why (if there is some sort of voodoo at work) or why not.
Cheers,
Yes, this code is wrong - the outcome is not really defined, but it would be quite reasonable for it to throw an exception at the mrEvent.WaitOne(), since mrEvent is the almost-certainly-now-disposed ManualResetEvent. Technically there's a chance that the worker thread was all ready to go, and the worker thread did its "some processing..." faster than the primary thread did the "some other processing...", but: I wouldn't rely on it. So in most cases: mrEvent is dead already.
As for how to avoid this: perhaps this simply isn't a scenario for using. But it occurs that since the worker thread does a WaitOne, the worker thread's WaitOne cannot complete before the primary thread performs the mre.Set() call - so you could exploit that and move the using to the worker:
var mre = new ManualResetEvent(false);
var bgWkr = new BackgroundWorker();
bgWkr.DoWork += delegate(object sender, DoWorkEventArgs e)
{
using(var mrEvent = e.Argument as ManualResetEvent)
{
// some processing...
mrEvent.WaitOne();
}
// broadcast an event
};
bgWkr.RunWorkerAsync(mre);
// some other processing...
// hook into the same event
mre.Set();
Note, however, that this raises an interesting question of what happens if the primary thread throws an exception in the "some other processing..." - the call to mre.Set() would never be reached, and the worker thread would never exit. You might want to do the mre.Set() in a finally:
var mre = new ManualResetEvent(false);
try {
var bgWkr = new BackgroundWorker();
bgWkr.DoWork += delegate(object sender, DoWorkEventArgs e)
{
using(var mrEvent = e.Argument as ManualResetEvent)
{
// some processing...
mrEvent.WaitOne();
}
// broadcast an event
};
bgWkr.RunWorkerAsync(mre);
// some other processing...
}
finally {
// hook into the same event
mre.Set();
}
In response to my comment (rather than proposing the answer to the question), I created a class to close the ManualResetEvent once done with it without the need to track when the last thread has finished using it. Thanks to Marc Gravell for the idea to close it once the WaitOne has completed. I am exposing it here should anybody else need it.
P.S. I'm constrained to .NET 3.5... hence why I am not using the ManualResetEventSlim.
Cheers,
Sean
public class OneTimeManualResetEvent
{
private ManualResetEvent _mre;
private volatile bool _closed;
private readonly object _locksmith = new object();
public OneTimeManualResetEvent()
{
_mre = new ManualResetEvent(false);
_closed = false;
}
public void WaitThenClose()
{
if (!_closed)
{
_mre.WaitOne();
if (!_closed)
{
lock (_locksmith)
{
Close();
}
}
}
}
public void Set()
{
if (!_closed)
_mre.Set();
}
private void Close()
{
if (!_closed)
{
_mre.Close();
_closed = true;
}
}
}

How to raise cross thread event

How can I raise the the event GeocodeAddressEventHandler from another thread?
System.Threading.Thread MapThread;
WinformMap map ;
public delegate void GeocodeAddressEventHandler(object sender, EventArgs e);
public event GeocodeAddressEventHandler GeocodeAddressEvent;
//How to Raise this Event from another thread??
public void GeocodeAddress_Raised(object sender, EventArgs e)
{
MapLib.GeocodeAddress("12798 1ST ST", "", "", "");
}
public bool LoadMap(string restorepoint)
{
////////////////////////Engine Controls////////////////////////////////////////////////////////
try
{
System.ServiceModel.OperationContext context = System.ServiceModel.OperationContext.Current;
//This is to instantiate a winform from a Console (will convert to service shortly)
MapThread = new System.Threading.Thread(new System.Threading.ThreadStart(delegate
{
using (System.ServiceModel.OperationContextScope scope = new System.ServiceModel.OperationContextScope(context))
{
this.GeocodeAddressEvent += new GeocodeAddressEventHandler(GeocodeAddress_Raised);
}
}));
MapThread.SetApartmentState(System.Threading.ApartmentState.STA);
MapThread.Start();
MapThread.Join();
}
catch (Exception ex)
{
return false;
}
return true;
}
Actually it turned out that the thread was terminating after the scope of the delegate terminated. This might be a dumb way to do it, but I put a while Queue.empty { sleep } in that scope so it never terminated, then I launched the LoadMap from yet another thread, so that it jam up my WCF service waiting for the neverending queue to terminate.
Take a look at
http://www.codeproject.com/KB/cs/Cross_thread_Events.aspx
See also BackgroundWorker class : http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
Take a look at the Invoke() method:
http://msdn.microsoft.com/library/zyzhdc6b.aspx

How to avoid spaghetti code when using completion events?

Somehow I cannot believe that I am the first one to run into that problem (and I don't want to believe that I am the only one stupid enough not to see a solution directly), but my search-fu was not strong enough.
I regularly run into a situation, when I need to do a few time-consuming steps one after the other. The workflow looks like
var data = DataGetter.GetData();
var processedData = DataProcessor.Process(data);
var userDecision = DialogService.AskUserAbout(processedData);
// ...
I don't want to block the UI during each step, so every method does return immediately, and raises an event once it has finished. Now hilarity ensues, since the above code block mutates into
DataGetter.Finished += (data) =>
{
DataProcessor.Finished += (processedData) =>
{
DialogService.Finished(userDecision) =>
{
// ....
}
DialogService.AskUserAbout(processedData);
}
DataProcessor.Process(data);
};
DataGetter.GetData();
This reads too much like Continuation-passing style for my taste, and there has to be a better way to structure this code. But how?
The correct way would be to design your components in a synchronous way and execute the complete chain in a background thread.
The Task Parallel Library can be useful for such code. Note that TaskScheduler.FromCurrentSynchronizationContext() can be used to run the task on the UI thread.
Task<Data>.Factory.StartNew(() => GetData())
.ContinueWith(t => Process(t.Result))
.ContinueWith(t => AskUserAbout(t.Result), TaskScheduler.FromCurrentSynchronizationContext());
You can put everything into a BackgroundWorker. The following code would only work properly if you change the methods GetData, Process, and AskUserAbout to run synchronously.
Something like this:
private BackgroundWorker m_worker;
private void StartWorking()
{
if (m_worker != null)
throw new InvalidOperationException("The worker is already doing something");
m_worker = new BackgroundWorker();
m_worker.CanRaiseEvents = true;
m_worker.WorkerReportsProgress = true;
m_worker.ProgressChanged += worker_ProgressChanged;
m_worker.DoWork += worker_Work;
m_worker.RunWorkerCompleted += worker_Completed;
}
private void worker_Work(object sender, DoWorkEventArgs args)
{
m_worker.ReportProgress(0, "Getting the data...");
var data = DataGetter.GetData();
m_worker.ReportProgress(33, "Processing the data...");
var processedData = DataProcessor.Process(data);
// if this interacts with the GUI, this should be run in the GUI thread.
// use InvokeRequired/BeginInvoke, or change so this question is asked
// in the Completed handler. it's safe to interact with the GUI there,
// and in the ProgressChanged handler.
m_worker.ReportProgress(67, "Waiting for user decision...");
var userDecision = DialogService.AskUserAbout(processedData);
m_worker.ReportProgress(100, "Finished.");
args.Result = userDecision;
}
private void worker_ProgressChanged(object sender, ProgressChangedEventArgs args)
{
// this gets passed down from the m_worker.ReportProgress() call
int percent = args.ProgressPercentage;
string progressMessage = (string)args.UserState;
// show the progress somewhere. you can interact with the GUI safely here.
}
private void worker_Completed(object sender, RunWorkerCompletedEventArgs args)
{
if (args.Error != null)
{
// handle the error
}
else if (args.Cancelled)
{
// handle the cancellation
}
else
{
// the work is finished! the result is in args.Result
}
}

C# Threading and using AutoResetEvent

I have the following code in a class library. And I wait for a call back into my main application. I am making a DownloadStringAsync call so I have to wait a few seconds to get the callback after it has finished. I have a 3 of these calls to wait for, so in my main application I am using AutoResetEvent to wait all of them to finish. So I will block until they have been set in the callback function.
However, after testing the callback don't get called. I am thinking when the code gets blocked by the AutoResetEvent its blocking the DownloadStringAsync. As when I comment out this code everything works fine.
So I think as soon as I make a call to: objNoGateway.NoGatewayStatus(sipUsername, statusDisplay1.PhoneNumber);
And when the code reaches here: handle.WaitOne();
It will block the code in the class library.
Many thanks for any advice.
In my class library code sample.
// Event handler that makes a call back in my main application
// Event handler and method that handles the event
public EventHandler<NoGatewayEventArgs> NoGatewayCompletedEvent;
// The method that raises the event.
private void OnNoGatewayCompleted(object sender, NoGatewayEventArgs e)
{
if (NoGatewayCompletedEvent != null)
{
NoGatewayCompletedEvent(this, e);
}
}
// Start the Async call to find if NoGateway is true or false
public void NoGatewayStatus(string sipUsername, string phoneNumber)
{
string strURL = string.Format("http://xxxxxxxxxxxxxxx={0}&CalledNumber={1}", sipUsername, phoneNumber);
if (!wc.IsBusy)
{
try
{
string errorMsg = string.Empty;
wc.DownloadStringAsync(new Uri(strURL));
}
catch (WebException ex)
{
Console.WriteLine("IsNoGateway: " + ex.Message);
}
catch (Exception ex)
{
Console.WriteLine("IsNoGateway: " + ex.Message);
}
}
else
{
Console.WriteLine("WebClient: IsNoGateWay(): Busy please try again");
}
}
void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null)
{
if (e.Result == "No gateway")
{
OnNoGatewayCompleted(this, new NoGatewayEventArgs(validateResponse_e.VALIDATION_FAILED));
Console.WriteLine("NoGatway() DownloadedCompleted: " + e.Result);
}
else
{
OnNoGatewayCompleted(this, new NoGatewayEventArgs(validateResponse_e.OK));
Console.WriteLine("NoGateway() DownloadCompleted: " + e.Result);
}
}
else
{
this.OnNoGatewayCompleted(this, new NoGatewayEventArgs(validateResponse_e.SERVER_FAILED));
Console.WriteLine("No Gateway: DownloadCompleted() Error: " + e.Error.Message);
}
}
In my main application I register this callback. And wait for the for the result. Then set the AutoResetEvent.
ManualResetEvent[] waitValidateCallResponse = new ManualResetEvent[]
{ new ManualResetEvent(false), new ManualResetEvent(false), new ManualResetEvent(false) };
// Event handler for NoGateway event
private void OnNoGatewayCompleted(object sender, NoGatewayEventArgs e)
{
Console.WriteLine("OnNoGatewayComleted: " + e.noGateway);
waitValidateCallResponse[0].Set();
}
The part when I am calling and blocking.
NoGateway objNoGateway = new NoGateway()
objNoGateway.NoGatewayCompletedEvent += new EventHandler<NoGatewayEventArgs>(this.OnNoGatewayCompleted);
objNoGateway.NoGatewayStatus(sipUsername, statusDisplay1.PhoneNumber);
// Block here - Wait for all reponses to finish before moving on
waitEvent.WaitOne(5000, true);
Console.WriteLine("All thread finished");
======================== Edit and added the other 2 callbacks as not to confuse the issue of me just having only one ======================
private void OnCalledNumberBlockedCompleted(object sender, CalledNumberBlockedEventArgs e)
{
Console.WriteLine("OnCalledNumberBlockedCompleted: " + e.CalledNumberBlocked);
waitValidateCallResponse[1].Set();
}
private void OnValidTelephoneNumberCompleted(object sender, ValidTelephoneNumberEventArgs e)
{
Console.WriteLine("OnValidTelephoneNumberCompleted: " + e.validTelephoneNumber);
waitValidateCallResponse[2].Set();
}
Is it as simple as: you always call Set on index 0?
private void OnNoGatewayCompleted(object sender, NoGatewayEventArgs e)
{
Console.WriteLine("OnNoGatewayComleted: " + e.noGateway);
waitValidateCallResponse[0].Set();
}
Try something along these lines:
public void NoGatewayStatus (string sipUsername, string phoneNumber) {
string strURL = string.Format( "http://xxxxxxxxxxxxxxx={0}&CalledNumber={1}", sipUsername, phoneNumber );
ManualResetEvent wait1 = new ManualResetEvent( false );
WebClient wc = new WebClient();
Thread thr = new Thread( DownloadSomeStuff );
thr.Start( new DlArguments( strURL, wait1 ) );
// do the other three
if ( !wait1.WaitOne( 10000 ) ) {
Console.WriteLine( "DownloadSomeStuff timed out" );
return;
}
if ( !wait2.WaitOne( 10000 ) ) {
Console.WriteLine( "DownloadOtherStuff timed out" );
return;
}
if ( !wait3.WaitOne( 10000 ) ) {
Console.WriteLine( "DownloadMoreStuff timed out" );
return;
}
}
public void DownloadSomeStuff (object p_args) {
DlArguments args = (DlArguments) p_args;
try {
WebClient wc = new WebClient();
wc.DownloadString( args.Url );
args.WaitHandle.Set();
} catch ( Exception ) {
// boring stuff
}
}
private class DlArguments
{
public DlArguments (string url, ManualResetEvent wait_handle) {
this.Url = url;
this.WaitHandle = wait_handle;
}
public string Url { get; set; }
public ManualResetEvent WaitHandle { get; set; }
}
Does this do it?
After lots of edits, I think I might understand the problem. Windows Forms applications have one main thread; this thread is used to process messages. So when your main thread is blocking, your application can't receive events. And you use WaitOne to keep the main thread blocked.
I'd move the WaitOne() checks to a separate timer thread.
Or you could wait for a limited time, and instruct the application to process messages in between:
foreach (WaitHandle handle in waitValidateCallResponse)
{
while (!handle.WaitOne(300))
Application.ProcessMessages();
Console.WriteLine("events.WaitOne(): " + handle.ToString());
}
The later approach is not something you should do in a library though. It's something of an anti-pattern I think.
The snippet code is peculiar
// Event handler that makes a call back in my main application
// Event handler and method that handles the event
public EventHandler<NoGatewayEventArgs> NoGatewayCompletedEvent;
// The method that raises the event.
public void OnNoGatewayCompleted(object sender, NoGatewayEventArgs e)
{
if (NoGatewayCompletedEvent != null)
{
NoGatewayCompletedEvent(this, e);
}
}
However in the 2nd last snippet, you attach an event handler for this event as follows.. OnNoGatewayCompleted seems to be a helper method to raise the event.. (it should not be public) but here it seems you have the event handler raise the event again. Unless you have 2 methods named OnNoGatewayCompleted (I'm hoping not)
objNoGateway.NoGatewayCompletedEvent
+= new EventHandler<NoGatewayEventArgs>(this.OnNoGatewayCompleted);
If you're looking for the waitHandles to be signalled in the event handler, shouldn't the methods OnCalledNumberBlockedCompleted be hooked up to the event instead.
PS: As Marc pointed out.. use WaitHandle.WaitAll ( the for loop demands that the async operations complete in order which may not be the case )
Use WaitHandle.WaitAny(handleArray); to wait on all the handles in the handle array instead of handle.WaitOne(); in a loop

Categories

Resources