c# .net WCF Eventhandler completion - c#

How do I determine when a Eventhandler for a WCF is complete?
I have two static variables that don't get set until the loop I am using to check the status is complete.
Create the variables and call the WCF using the Asynch functions created
static var globalResults;
static bool myEventComplete;
main()
{
globalResults = null;
myEventComplete = false;
WCFClient wcf = new WCFClient();
//create event handler for the WCF asynch call
wcf.MyFuncCompleted += new EventHandler<MyFuncCompletedEventArgs>wcf_MyFuncCompleted);
wcf.MyFuncAsync(wcfParameter.ToString());
int counter = 1;
//Need to determine when the event handler is complete to then use the data returned from the WCF
while (myEventComplete == false && globalResults == null && counter < 10000)
{
counter++;
}
}
//Eventhandler
public static void wcf_MyFuncCompleted(object sender, MyFuncCompletedEventArgs e)
{
globalResults = e.Result;
myEventComplete = true;
}
The eventhandler eventually updates the variables after the loop has completed.
If I duplicate the loop into two sections - the variables get updated in between the two loops - it seems that the event handler isn't running until after the loop (which I don't think is the case) - I just don't know how to get the update values from within the loop.

What's probably happening is that loop is running almost instantly (counting to 10,000 takes practically no time at all). And I'd actually expect the compiler to optimize away the loop unless you use the counter further down.
If the goal is to just do something when the event fires - just call the method you want to run when it completes from within the event itself. There isn't any need for the loop. Are you just attempting to "block" the code until the event fires/completes? I probably wouldn't since it's not needed - just continue the rest of your code that is called by the event itself.

I agree with #Paul Mrozowski.
However, if you have to block the thread, you can block it by defining a static AutoResetEvent object, and in your main call WaitOne() method to block the thread and unblock it with Set()
I do not recommend this if you don't badly need it. You usually can call whatever you want in your wcf_MyFuncCompleted
your main will probably look like this:
// You may reduce its accessibility if needed
public static AutoResetEvent SignalMyThread=new AutoResetEvent(false);
main()
{
WCFClient wcf = new WCFClient();
//create event handler for the WCF asynch call
wcf.MyFuncCompleted += new EventHandler<MyFuncCompletedEventArgs>wcf_MyFuncCompleted);
wcf.MyFuncAsync(wcfParameter.ToString());
// wait for one minute at most, you can specify no time to make it wait indefinitely
SignalMyThread.WaitOne(60000);
}
And just call set in your event handler:
public static void wcf_MyFuncCompleted(object sender, MyFuncCompletedEventArgs e)
{
SignalMyThread.Set();
}

Related

Working with an event handler - but not always.. (How do i...)

I'm quite new to C# and certainly OOP concepts.. so forgive the stupidity of my question.
I have a system I wish to communicate with, It has a number of commands that can be called with an associated response. (Communication is done via TCP/IP or Serial) (I implemented an Interface with SendMessage so that I can use multiple transport mechanisms)
I want to create a method for each command and then expose these, which is simple enough. The device also lets say 'broadcasts' messages as well which I want to act on, so I was using an event handler for this which works well..
At the moment in the event handler I catch OK and ERROR style messages, but ideally I would like to also be able to send the command from the above method and catch an error and return a bool value based on the command.
Can anyone think of a way I can do something like this and point me in the right direction?
Thanks
David
You can use helper to wait for event. Some ugly code from past:
public class ComWait
{
ManualResetEvent _waitEvent;
SomeEvent _eventHandler;
public ComWait()
{
_waitEvent = new ManualResetEvent(false);
_eventHandler = new SomeEvent(Watch);
}
void Watch()
{
_waitEvent.Set();
}
public bool Wait(int time = 3000)
{
_waitEvent.Reset();
SomeEvent += _eventHandler;
bool result = _waitEvent.WaitOne(time, false);
SomeEvent -= _eventHandler;
return result;
}
}
Usage is
ComWait wait = new ComWait();
if(!wait.Wait())
return; // timeout
// process
It will simply block synchronous method until event is rised or timeout occurs. It should be easy to add parameters: to unblock on specific event and to pass event handler parameters back to caller.
Otherwise I would simply have method inside communication class to use as a blocker:
readonly object _waitLock = new object();
public void Wait()
{
lock (_waitLock)
if (!Monitor.Wait(_waitLock, 3000))
throw new TimeoutException("No communications");
}
Signal at same time as you rise event:
lock (_waitLock)
Monitor.PulseAll(_waitLock);

Function runs fine the first time, but second time it produces 2 windows as opposed to just one

The purpose of this code is to accept text from a form, pass it on to a function and thow this text inside a background worker that will execute a second function. This background worker has its do_work and work_completed event listeners defined. The problem is when I run this code for the first time the application is running, it works fine. The next time I execute "fetchFunction" and subsequently the fetchStuff function, I get 2 windows or 2 objfrmMChild showing instead of 1 like the first time I ran it.
I ran my code in debug mode and saw that the RunWorkerCompletedEventHandler runs once and pops the window up, but then it circles back a second time and runs again. Any idea why?
public void fetchFunction(TextBox text)
{
fetch.WorkerSupportsCancellation = true;
if (!fetch.IsBusy)
{
Lists.BGWParams bgwp = new Lists.BGWParams();
bgwp.Value = text.Text.Trim();
fetchStuff(bgwp);
}
else
{
fetch.CancelAsync();
}
}
private void fetchStuff(Lists.BGWParams parameters)
{
DoWorkEventHandler dweh = (object senderA, DoWorkEventArgs argsA) =>
{
if (argsA != null && argsA.Argument is Lists.BGWParams)
{
Lists.BGWParams p = argsA.Argument as Lists.BGWParams;
p.Result2 = genericClass.fetchOtherStuff_DoWork(p.Value);
argsA.Result = argsA.Argument;
}
};
RunWorkerCompletedEventHandler rwceh = (object senderB, RunWorkerCompletedEventArgs argsB) =>
{
if (argsB != null && argsB.Result is Lists.BGWParams)
{
Lists.BGWParams p = argsB.Result as Lists.BGWParams;
frmMChild objfrmMChild = new frmMChild(this);
countResults = p.Result2;
objfrmMChild.MdiParent = this;
objfrmMChild.Show();
objfrmMChild.populateDataGridwithStuff(p.Result2, p.Value);
}
};
fetch.DoWork += dweh;
fetch.RunWorkerCompleted += rwceh;
fetch.RunWorkerAsync(parameters);
}
Your fetchStuff is referencing a BackgroundWorker that is an instance field. Each time you're calling fetchStuff you're adding yet another handler for each of those events. The first time there's one, the second time there's two, the third time there's three. You're doing the work that many times, and displaying the result that many times.
Just make the BGW local to that method. If you create a new BGW each time you won't have that problem. If you do this you still need to support cancellation though. The easiest way to do that is to create a CancellationTokenSource as a field that the BGW uses. Create a new CTS each time you start the operation. (That said, you never check for cancellation in your DoWork handlers, so you're not actually cancelling anything currently.)
The alternative is to attach these event handlers when creating this class, rather than inside of fetchStuff; have fetchStuff just call RunWorkerAsync. (Or for that matter just omit it entirely and have whatever calls it call RunWorkeAsync.)

ManualResetEvent wait doesn't release after being set

I'm downloading two JSON files from the webs, after which I want to allow loading two pages, but not before. However, the ManualResetEvent that is required to be set in order to load the page never "fires". Even though I know that it gets set, WaitOne never returns.
Method that launches the downloads:
private void Application_Launching(object sender, LaunchingEventArgs e)
{
PhoneApplicationService.Current.State["doneList"] = new List<int>();
PhoneApplicationService.Current.State["manualResetEvent"] = new ManualResetEvent(false);
Helpers.DownloadAndStoreJsonObject<ArticleList>("http://arkad.tlth.se/api/get_posts/", "articleList");
Helpers.DownloadAndStoreJsonObject<CompanyList>("http://arkad.tlth.se/api/get_posts/?postType=webbkatalog", "catalog");
}
The downloading method, that sets the ManualResetEvent
public static void DownloadAndStoreJsonObject<T>(string url, string objName)
{
var webClient = new WebClient();
webClient.DownloadStringCompleted += (sender, e) =>
{
if (!string.IsNullOrEmpty(e.Result))
{
var obj = ProcessJson<T>(e.Result);
PhoneApplicationService.Current.State[objName] = obj;
var doneList = PhoneApplicationService.Current.State["doneList"] as List<int>;
doneList.Add(0);
if (doneList.Count == 2) // Two items loaded
{
(PhoneApplicationService.Current.State["manualResetEvent"] as ManualResetEvent).Set(); // Signal that it's done
}
}
};
webClient.DownloadStringAsync(new Uri(url));
}
The waiting method (constructor in this case)
public SenastePage()
{
InitializeComponent();
if ((PhoneApplicationService.Current.State["doneList"] as List<int>).Count < 2)
{
(PhoneApplicationService.Current.State["manualResetEvent"] as ManualResetEvent).WaitOne();
}
SenasteArticleList.ItemsSource = (PhoneApplicationService.Current.State["articleList"] as ArticleList).posts;
}
If I wait before trying to access that constructor, it easily passes the if-statement and doesn't get caught in the WaitOne, but if I call it immediately, I get stuck, and it never returns...
Any ideas?
Blocking the UI thread must be prevented at all costs. Especially when downloading data: don't forget that your application is executing on a phone, which has a very instable network. If the data takes two minutes to load, then the UI will be freezed for two minutes. It would be an awful user experience.
There's many ways to prevent that. For instance, you can keep the same logic but waiting in a background thread instead of the UI thread:
public SenastePage()
{
// Write the XAML of your page to display the loading animation per default
InitializeComponent();
Task.Factory.StartNew(LoadData);
}
private void LoadData()
{
((ManualResetEvent)PhoneApplicationService.Current.State["manualResetEvent"]).WaitOne();
Dispatcher.BeginInvoke(() =>
{
SenasteArticleList.ItemsSource = ((ArticleList)PhoneApplicationService.Current.State["articleList"]).posts;
// Hide the loading animation
}
}
That's just a quick and dirty way to reach the result you want. You could also rewrite your code using tasks, and using Task.WhenAll to trigger an action when they're all finished.
Perhaps there is a logic problem. In the SenastePage() constructor you are waiting for the set event only if the doneList count is less than two. However, you don't fire the set event until the doneList count is equal to two. You are listening for the set event before it can ever fire.

Wait on Class Method to be finished C#

I need to Download a File from a Https Source.
I'll do this asynchron like this (works so far):
void doChecksbeforDownload(){
//Do some Checks
DownloadFileAsync();
}
void DownloadFileAsync(){
...
...
this.client.UploadStringCompleted += new UploadStringCompletedEventHandler(client_UploadStringCompleted);
this.client.Headers["Content-Type"] = "application/x-www-form-urlencoded";
this.client.UploadStringAsync(new Uri(url), "POST", PostParameter);
...
...
}
and call the client_UploadStringCompleted() Method when finished:
void client_UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
{
//Do Check here
}
So far so good. Now I put all this in a class "Functions" and call the Method like this:
Functions f = new Functions();
f.doChecksbeforeDownload();
I want doChecksbeforeDownload() to wait until the clientUloadStringCompleted is FINISHED.
How do I do I tell doChecksbeforeDownload to wait until the the Async call in DownloadFilesAsync is done and ready.
Call doChecksbeforeDownload()
ChecksbeforeDownload()->DownloadFileAsync()
ChecksbeforeDownload()->Waits.......
DownloadFileAsync() -> Completet & Ready
ChecksbeforeDownload()->returns FOO to Main Class
Are there any best practices / examples to achieve this? I stuck in this point.
Thanks in advance
Hannes
You will want to use the synchronization objects exposed in .NET.
Check out this link. Here's an excerpt:
class BasicWaitHandle
{
static EventWaitHandle _waitHandle = new AutoResetEvent (false);
static void Main()
{
new Thread (Waiter).Start();
Thread.Sleep (1000); // Pause for a second...
_waitHandle.Set(); // Wake up the Waiter.
}
static void Waiter()
{
Console.WriteLine ("Waiting...");
_waitHandle.WaitOne(); // Wait for notification
Console.WriteLine ("Notified");
}
}
NOTE: Be careful making your reset events static, etc. Then you'll be introducing thread safety issues. The above example is only static for simplicity.
In your case, you'd want to make to make the autoreset event a member of your class that is performing the asynchronous. In your function, after you start the asynchronous call, wait on your handle. In the completion event, set your event which should unblock your wait handle.
Consider that you may want to introduce timeouts for the call to WaitOne(), etc.
You should look for some WaitHandle derived class to accomplish the task.
I would use ManualResetEvent as I think is one of the easiest one.
I'm just spit balling here, but how about this:
In DownloadFileAsync() set a flag like DownloadInProgress
In doChecksbeforeDownload
If DownloadInProgress Then set flag WaitingForDownloadCompletion
Else Continue
In client_UploadStringCompleted()
Set DownloadInProgress = false
If WaitingForDownloadCompletion Then call doChecksbeforeDownload()
You can create a bool variable at the classlevel like
bool isFinished = false;
Then have your async set this value to true once it is done.
Then expose the isFinished varible as a public value.

Event gets triggered after timeout is over

I have to wait for an event to be triggered. My initial solution was to use AutoResetEvent and WaitOne(), but the event was always triggered just after the waiting timeout was over. So I went back to the approach below, but I still have the same problem. 2 or 3 seconds after the timeout is over the event gets triggered no matter what the timeout was.
_wait = true;
_delayedResponse = null;
var thread = new Thread(delegate
{
while (_wait)
{
Thread.Sleep(500);
if (_delayedResponse != null)
return;
}
});
thread.Start();
var received = thread.Join(_responseTimeout);
_wait = false;
if (!received)
throw new TimeoutException(
"Timeout for waiting for response reached.");
return _delayedResponse;
Here is the event handler code:
private void OnResponseArrived(object sender, ResponseEventArgs args)
{
_delayedResponse = args.VerificationResponse;
}
The event itself is triggered from another functions that calls the function above.
Basically it looks like this:
var result = DoStuff(); // Library function that is responsible for the event
if (result.Status == Status.Wait)
Wait(); // Function above
Does anyone have an idea what causes this problem and how I can solve it?
EDIT: No longer relevant. Forwarded the OnResponseArrived event, because I found no other solution in time.
Thread.Join is a blocking call - it'll stop the thread you're calling from doing any other work. My guess is that you're waiting for the event on a background thread, but the code that will raise your event is running on the same thread as the code you posted runs in.
By calling thread.Join you're blocking the thread that should be doing your processing. So, you wait for your timeout to expire... then whichever method your posted code is in completes... then your processing actually happens and the ResponseArrived event is raised.
It would be useful if you'd post the rest of your code, but the gist of the solution will be to run the actual work (whatever code raises the ResponseArrived event) in a background thread - and remove the extra threading from the code you posted.
EDIT in response to comment...
In order to synchronise your two pieces of code, you can use an AutoResetEvent. Instead of using Thread.Sleep and your other code, try something like this:
// create an un-signalled AutoResetEvent
AutoResetEvent _waitForResponse = new AutoResetEvent(false);
void YourNewWorkerMethod()
{
_delayedResponse = null;
var result = DoStuff();
// this causes the current thread to wait for the AutoResetEvent to be signalled
// ... the parameter is a timeout value in milliseconds
if (!_waitForResponse.WaitOne(5000))
throw new TimeOutException();
return _delayedResponse;
}
private void OnResponseArrived(object sender, ResponseEventArgs args)
{
_delayedResponse = args.VerificationResponse;
_waitForResponse.Set(); // this signals the waiting thread to continue...
}
Note that you'll need to dispose of the AutoResetEvent when you're done with it.
Well, the first thing you need to do is make sure that DoStuff actually works in a background thread.
If that is correct, the way your code is written right now, you don't event need to spawn a second thread, just to join it one line below, something like this would simply work (as a test):
// handler needs to be attached before starting
library.ResponseReceived += OnResponseReceived;
// call the method
var result = library.DoStuff();
// poll and sleep, but 10 times max (5s)
int watchdog = 10;
while (_delayedResponse == null && watchdog-- > 0)
Thread.Sleep(500);
// detach handler - always clean up after yourself
library.ResponseReceived -= OnResponseReceived;
Console.WriteLine(_delayedResponse != null);
If this works, and you are programming a WinForms app, then you should consider doing the entire thing in a background thread, and then notifying the UI when it's finished. Of course, you will need to provide more details if you need help with that.

Categories