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.
Related
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();
}
I have a method:
public void Run()
{
instalProgressPageViewModel.ExecuteButton_Click();
//waiting here
Environment.Exit(0);
}
Method Execute_Click() calls a installers of msi packages. Those installers run in separate threads:
this.uiDispatcher.BeginInvoke(
System.Windows.Threading.DispatcherPriority.Normal,
new InstallationCompleted(this.completeInstallDelegate),
installationState);
where:
this.completeInstallDelegate // method which should be called after the thread is done.
Waiting for function CompleteInstall is crucial as its finalize installation and begins installation next msi package in a list of packages.
In the sample code of method Run app is closed before anything can happen.
I tried putting:
while(true){}
In a place of // waiting here and put breakpoint in CompleteInstall method to check if it will be called but it wasn't hit. App is stucked in infite loop inside while.
What can I do to force my main thread to wait for threads and jump into completeinstall method when its called by delegate?
#Update:
With your suggestions my code looks like this:
there is
public static ManualResetEvent mre // global object initialized in main
and other class is:
public void Run()
{
instalProgressPageViewModel.ExecuteButton_Click();
mre.WaitOne();
Environment.Exit(0);
}
ExecuteButton_Click call this function:
public void StartProcessing()
{
var processor = new Action(this.DoProcessing);
processor.BeginInvoke(null, null);
}
now DoProcessing:
private void DoProcessing()
{
var installationState = this.Execute();
// Schedule the update function in the UI thread.
this.uiDispatcher.BeginInvoke(
System.Windows.Threading.DispatcherPriority.Normal,
new InstallationCompleted(this.completeInstallDelegate),
installationState);
}
and finally completeInstallDelegate
private void CompleteInstall(InstallationState installationState)
{
App.mre.Set();
/*
Some code
*/
this.PostInstallAndNext();
}
If I put break Point at the line App.mre.Set() it is never hit.
and for unknow reason for me the DoProcessing is called after mre.WaitOne(). Does Action and BeginInvoke work out of sync too?
Thanks for updating the question.
It looks like you are never creating an actual new Thread, i.e. you are suspending the main thread and effectively deadlocking your application.
You could create an new Thread here:
public void StartProcessing()
{
var thread = new Thread(() => this.DoProcessing);
thread.Start();
}
You could use the ManualResetEvent class.
Create a ManualResetEvet
ManualResetEvent mre = new ManualResetEvent(false);
In the Main method wait for this event to get signalled.
mre.WaitOne();
In your delegate (when the work is finished), signal the event.
mre.Set();
A simple solution would be to use ManualResetEvent.
You would then have a blocking call to WaitOne, until you call Set from the other thread.
I am working on a legacy application that is built on top of NET 3.5. This is a constraint that I can't change.
I need to execute a second thread to run a long running task without locking the UI. When the thread is complete, somehow I need to execute a Callback.
Right now I tried this pseudo-code:
Thread _thread = new Thread(myLongRunningTask) { IsBackground = True };
_tread.Start();
// wait until it's done
_thread.Join();
// execute finalizer
The second option, which does not lock the UI, is the following:
Thread _thread = new Thread(myLongRunningTask) { IsBackground = True };
_tread.Start();
// wait until it's done
while(_thread.IsAlive)
{
Application.DoEvents();
Thread.Sleep(100);
}
// execute finalizer
Of course the second solution is not good cause it overcharge the UI.
What is the correct way to execute a callback when a _thread is complete? Also, how do I know if the thread was cancelled or aborted?
*Note: * I can't use the BackgroundWorker and I can't use the Async library, I need to work with the native thread class.
There are two slightly different kinds of requirement here:
Execute a callback once the long-running task has completed
Execute a callback once the thread in which the long-running task was running has completed.
If you're happy with the first of these, the simplest approach is to create a compound task of "the original long-running task, and the callback", basically. You can even do this just using the way that multicast delegates work:
ThreadStart starter = myLongRunningTask;
starter += () => {
// Do what you want in the callback
};
Thread thread = new Thread(starter) { IsBackground = true };
thread.Start();
That's very vanilla, and the callback won't be fired if the thread is aborted or throws an exception. You could wrap it up in a class with either multiple callbacks, or a callback which specifies the status (aborted, threw an exception etc) and handles that by wrapping the original delegate, calling it in a method with a try/catch block and executing the callback appropriately.
Unless you take any special action, the callback will be executed in the background thread, so you'll need to use Control.BeginInvoke (or whatever) to marshal back to the UI thread.
I absolutely understand your requirements, but you've missed one crucial thing: do you really need to wait for the end of that thread synchronously? Or maybe you just need to execute the "finalizer" after thread's end is detected?
In the latter case, simply wrap the call to myLongRunningTask into another method:
void surrogateThreadRoutine() {
// try{ ..
mytask();
// finally { ..
..all 'finalization'.. or i.e. raising some Event that you'll handle elsewhere
}
and use it as the thread's routine. That way, you'll know that the finalization will occur at the thread's and, just after the end of the actual job.
However, of course, if you're with some UI or other schedulers, the "finalization" will now run on yours thread, not on the "normal threads" of your UI or comms framework. You will need to ensure that all resources are external to your thread-task are properly guarded or synchronized, or else you'll probably clash with other application threads.
For instance, in WinForms, before you touch any UI things from the finalizer, you will need the Control.InvokeRequired (surely=true) and Control.BeginInvoke/Invoke to bounce the context back to the UI thread.
For instance, in WPF, before you touch any UI things from the finalizer, you will need the Dispatcher.BeginInvoke..
Or, if the clash could occur with any threads you control, simple proper lock() could be enough. etc.
You can use a combination of custom event and the use of BeginInvoke:
public event EventHandler MyLongRunningTaskEvent;
private void StartMyLongRunningTask() {
MyLongRunningTaskEvent += myLongRunningTaskIsDone;
Thread _thread = new Thread(myLongRunningTask) { IsBackground = true };
_thread.Start();
label.Text = "Running...";
}
private void myLongRunningTaskIsDone(object sender, EventArgs arg)
{
label.Text = "Done!";
}
private void myLongRunningTask()
{
try
{
// Do my long task...
}
finally
{
this.BeginInvoke(Foo, this, EventArgs.Empty);
}
}
I checked, it's work under .NET 3.5
You could use the Observer Pattern, take a look here:
http://www.dofactory.com/Patterns/PatternObserver.aspx
The observer pattern will allow you, to notify other objects which were previously defined as observer.
A very simple thread of execution with completion callback
This does not need to run in a mono behavior and is simply used for convenience
using System;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;
public class ThreadTest : MonoBehaviour
{
private List<int> numbers = null;
private void Start()
{
Debug.Log("1. Call thread task");
StartMyLongRunningTask();
Debug.Log("2. Do something else");
}
private void StartMyLongRunningTask()
{
numbers = new List<int>();
ThreadStart starter = myLongRunningTask;
starter += () =>
{
myLongRunningTaskDone();
};
Thread _thread = new Thread(starter) { IsBackground = true };
_thread.Start();
}
private void myLongRunningTaskDone()
{
Debug.Log("3. Task callback result");
foreach (int num in numbers)
Debug.Log(num);
}
private void myLongRunningTask()
{
for (int i = 0; i < 10; i++)
{
numbers.Add(i);
Thread.Sleep(1000);
}
}
}
Try to use ManualRestEvent to signal of thread complete.
Maybe using conditional variables and mutex, or some functions like wait(), signal(), maybe timed wait() to not block main thread infinitely.
In C# this will be:
void Notify()
{
lock (syncPrimitive)
{
Monitor.Pulse(syncPrimitive);
}
}
void RunLoop()
{
for (;;)
{
// do work here...
lock (syncPrimitive)
{
Monitor.Wait(syncPrimitive);
}
}
}
more on that here:
Condition Variables C#/.NET
It is the concept of Monitor object in C#, you also have version that enables to set timeout
public static bool Wait(
object obj,
TimeSpan timeout
)
more on that here:
https://msdn.microsoft.com/en-us/library/system.threading.monitor_methods(v=vs.110).aspx
I have 2 async processes that need to be called one after the other (one is an XML creation backgroundworker and the other is a raring BW that uses the XML files created in the first process). The main reason for these threads is to stop the UI freezing and provide a status update by the way of a progress bar - as such a synchronous approach is not desirable/possible.
if (!CreateXMLBW.IsBusy)
{
CreateXMLBW.RunWorkerAsync("");
}
if (!CreateRarBW.IsBusy)
{
CreateRarBW.RunWorkerAsync();
}
I cannot put the second BW inside the first's completion event as the processes can be used separately and as such if I just want to create the XML files I can do that.
I have tried using AutoResetEvent and WaitOne but this (for whatever reason) still doesn't work.
Are there any other ways I can wait for a BW to complete without freezing the main UI thread?
Your scenario is exactly what Task was designed for. In your particular case your code might look like this:
public delegate void UpdateUI(int progress);
private void RunOneAfterAnotherAsync()
{
Task<XmlElement> task = Task.Factory.StartNew<XmlElement>(CreateXMLBW);
task.ContinueWith(CreateRarBW);
}
private XmlElement CreateXMLBW()
{
// your code
// progress
progressBar1.Invoke((UpdateUI)UpdateProgressBar, new object[] {progressValue});
// result
XmlDocument doc = new XmlDocument();
return doc.CreateElement("element");
}
private void CreateRarBW(Task<XmlElement> task)
{
CreateRarBW(task.Result);
}
private void CreateRarBW(XmlElement arg)
{
// your code
}
public void UpdateProgressBar(int value)
{
this.progressBar1.Value = value;
}
RunOneAfterAnotherAsync is not blocking and your 2 methods run asynchronously one after another. CreateRarBW runs only if CreateXMLBW ends with no exception but you can change that by using additional arguments in ContinueWith.
You can do much more than this example shows - I encourage you to explore the Task class.
EDIT
I have extend the example a little bit to incorporate a result being passed from the first task into the second one. Also added UI progress example.
You could also use a Task like in this example:
class Program
{
static XElement CreateXml()
{
System.Threading.Thread.Sleep(1000);
return XElement.Parse(#"<FooBar>Hi!</FooBar>");
}
static void ProceedXml(XElement xml)
{
System.Threading.Thread.Sleep(1000);
Console.WriteLine(xml.ToString());
}
public static void Main()
{
Task.Factory.StartNew<XElement>(CreateXml)
.ContinueWith(t => ProceedXml(t.Result));
Console.ReadKey();
}
}
If you don't want block UI till waiting for event (so I suppose you're gonna do something)
you can raise an event at the end of the DoWork(), and UI thread can recieve it.
If you're using 4.0 and can avoid of using BackgroundWorker, you can make use of Task.ContinueWith from TPL.
A pseudocode may look like this:
Action action =(() => DoWorkMethod());
Task.Factory.StartNew(() => action()).ContinueWith(()=>CallAfterComplete());
Your UI can handle the RunWorkerCompleted event on the first BW and invoke the second BW.
I have a worker thread that may be active for short bursts of time and idle for rest of the time. I'm thinking to put the thread to sleep and then awake it when needed.
Any additional recommendations for this I should be aware of?
Thanks!
this is in C#/.NET4
You should probably not be using a persistent worker thread- use the thread pool. This is exactly what it is intended for.
ThreadPool.QueueUserWorkItem(() => {
// My temporary work here
});
If you insist on having a persistent worker thread, make it run this:
// This is our latch- we can use this to "let the thread out of the gate"
AutoResetEvent threadLatch = new AutoResetEvent(false);
// The thread runs this
public void DoBackgroundWork() {
// Making sure that the thread is a background thread
// ensures that the endless loop below doesn't prevent
// the program from exiting
Thread.IsBackground = true;
while (true) {
// The worker thread will get here and then block
// until someone Set()s the latch:
threadLatch.WaitOne();
// Do your work here
}
}
// To signal the thread to start:
threadLatch.Set();
Also note that if this background thread is going to interact with the user interface at all, you'll need to Invoke or BeginInvoke accordingly. See http://weblogs.asp.net/justin_rogers/pages/126345.aspx
Just use an event to pause the worker thread: reset - paused, set - unpaused (working) state.
Here is the draft version of code that demonstrates the approach.
class Worker
{
private Thread _thread;
// Un-paused by default.
private ManualResetEvent _notToBePaused = new ManualResetEvent(true);
public Worker()
{
_thread = new Thread(Run)
{
IsBackground = true
};
}
/// <summary>
/// Thread function.
/// </summary>
private void Run()
{
while (true)
{
// Would block if paused!
_notToBePaused.WaitOne();
// Process some stuff here.
}
}
public void Start()
{
_thread.Start();
}
public void Pause()
{
_notToBePaused.Reset();
}
public void UnPause()
{
_notToBePaused.Set();
}
}
Signaling with WaitHandle is the right way to go, but just to add on what others said already
I'd usually go with 2 signals working together, otherwise you wouldn't know whether to 'continue' or 'exit' when needed - or would have to resort to a less graceful way of doing that (stopping the thread - of course there are other ways of doing something like this, just one 'pattern'). So usually it works with an 'exit' signal and a 'new work available' signal - working in unison. e.g.
WaitHandle[] eventArray = new WaitHandle[2] { _exitEvent, _newWorkEvent };
while ((waitid = WaitHandle.WaitAny(eventArray, timeout, false)) > 1)
{
// do your work, and optionally handle timeout etc.
}
note:
exit is ManualResetEvent with 'false' initial state - 'Set' event to exit.
_newWork is either Manual in which case you need to pause/continue from outside which is what you wanted I think -
...or could also be new AutoResetEvent(false) which you 'signal' to do one loop of work, signal returns to 'false' right away - and you need to repeat that for each 'new batch' of work - this is a bit simplified.
(often that goes hand in hand with some 'messages' being passed along, synchronized of course in some way).
Hope this adds some more info,