Hopefully you can help.
Scenario
WPF Application calling a wcf Service to buy products etc...
A customer can select 20 products in the UI and press buy,now for each product that is processed I need to report a status EG("OK","Out of stock","Busy" etc...)
I have a txtReportProgress that is bind to a BuyCommand.
Problem
Even though everything seems to work ok and I receive a notification for each product processed it gets all out sync and not actually reporting the steps in the correct order.
I think this is todo with the fact that I have NOT implemented threading but I dont know how to do it.
I have read i can use "Dispatcher" i/o background worker but cannot make it work.
Noddy example here to give you an idea.
Can you help me and give me some pointers?
---CustomerViewModel
public ICommand BuyCommand
{
get
{
if (BuyCommand == null)
{
BuyCommand = new RelayCommand(param => Buy(), param => CanBuy);
}
return BuyCommand;
}
}
private void Buy()
{
ReportProgress("Buying Progress is starting");
ProductStatus status=myService.IsProductAvailable();
myService.ProcessProducts(); //For each product that is processed service does a callback and NotificationReceivedfromService is fired.THIS WORKS!!
ReportProgress(status);
var result =DoSomethingElse();
ReportProgress(result);
}
void NotificationReceivedFromService(object sender, StatusEventArg e)
{
//update the UI
ReportProgress(e.Message);
}
static bool CanBuy
{
get
{
return true;
}
}
public string CustomerLog
{
get { return _customerModel.CustomerLog; }
set
{
_customerModel.CustomerLog = value;
base.OnPropertyChanged("CustomerLog");
}
}
internal void ReportProgress(string text)
{
CustomerLog += text + Environment.NewLine;
}
What is the WCF communication channel? Are you making multiple requests to a service in parallel? I can't really see from your code where there is any multi-threading going on at all but I'm assuming that NotificationReceivedFromService is some kind of callback?
Anyhow, if you were using something like Dispatcher.BeginInvoke, your invokes should be executed in the order they were made as long as they all have the same dispatcher priority.
If however you are making multiple parallel requests to the service, you can't really control the order in which they will complete. You'll need to make one request, then make the next when the first completes, etc. Or you can change your design so that it doesn't depend on the order of operations.
As you get callbacks out of sync, obviously some multithreading is going on, perhaps without your realizing it. You are aware that that calls to WCF services can be handled asynchronously by the service itself? Read here for more information. Please elaborate on your question or show us some more code if you need more help.
As to Dispatchers and BackgroundWorkers, these are very different beasts:
Dispatcher.Invoke is used to update the UI from a different thread than the UI thread.
Backgroundworkers encapsulate tasks that run on the background, but conveniently have events that are thrown on the UI thread, thereby making it unnecessary to use the Dispatcher.Invoke call.
You can read more about BackgroundWorkers here
As mentioned already, the CallBack is asynchronous so you will have an ordering problem. can you arrange the call to the service in some way that you can bring back some token or other identifier that will help you report the progress in the correct order? Something you can sort on perhaps?
Related
I'm a newbie in C#, and I'm going to develop a small program using a third party network library to send the requests.
Suppose there have some requests (just simple strings) stored in the queue qTasks, and it will handle those requests one by one with the order as submitted, the queue can be updated during execution, and it should be stopped whenever there has error returned.
I can just use a for loop to call the send request command in the array one by one, but unfortunately the sendrequest command is an async method with callback OnStageChanged, and I need to check the result before sending the next request when the status is "Done".
I'm now using the following method to handle it:
In the main UI Thread,
// Put those request text in a queue names qTasks, then call a goNextTask() to process the request one by one.
// The queue can be updated by the UI thread at anytime, goNextTask will be called periodically to handle those pending request in the queue.
private void goNextTask(bool lastSuccess = true)
{
if (lastSuccess)
{
if (qTasks.Count > 0)
{
// continue to next request
string requestText = qTasks.Dequeue();
SendRequest(requestText, OnStageChangeHandler);
} else {
// Report for all request sent successfully
}
} else {
// stop and show error
}
}
The callback method OnStageChangeHandler will be called by the library whenever the stage changes, and it will have state "Done" when completed.
private void OnStageChangeHandler(object sender, StageChangeEventArgs e)
{
if (e.newState == SessionStates.Done)
{
// check result here
bool success = <...>
// then call the goNextTask in UI thread with the result of current request.
Application.Current.Dispatcher.BeginInvoke(
System.Windows.Threading.DispatcherPriority.Normal,
(Action)(() => goNextTask(success)));
}
}
Although it works fine now, I think it's a little bit stupid as it has a somewhat recursive flow (A -> B -> A -> B ->....).
I learnt that MS has improved the web request handling, so that it can work in sync mode.
I'd like to know if I can have a wrapper to make the above async call work as a sync call, so that it can be done in a simple flow as a loop like that:
while (qTaks.Count > 0)
{
if (!sendAndWaitReturn(qTasks.Dequeue())) {
// Report error and quit
}
}
// all tasks completed
This sendAndWaitReturn method will send the request, then wait for the status "Done", and then return the result.
I found some example that may use a control flag to indicate the status of the current request, and the callback function will update this control flag, while the UI thread will loop on this flag using a while loop:
while (!requestDone);
so that it will not continue to nextRequest until requestDone. But in this case, the UI will be blocked.
Is there any better way to convert the async call to work as a sync call without blocking the UI thread?
The difficulty you're going to run into is you have conflicting desires. On one hand, you want to avoid blocking the UI thread. On the other hand, you don't want to run things asynchronously and so you're going to block the UI thread.
You're going to have to pick one, and there's absolutely no reason to keep on doing things synchronously (especially in light of blocking the UI thread). If it hurts when you do that, don't do that.
You haven't specified, but I'm guessing that you're starting this processing from a button click event. Make the method invoked by that click event async. For example:
private async void StartProcessing_Click(object sender, EventArgs e)
{
await Task.Run(() => StartProcessing());
}
There, you've started processing and the UI thread isn't tied up.
The next thing is that, you're right, having the event behave in that cyclical manner is silly. The event is to notify someone that the state has changed, its goal isn't to manage queue policy. The queue should manage queue policy (or if you'd rather not abstract that out, the method that processes requests).
So how would you do that? Well, you've said that SendRequest hands the session object back to the caller. The caller is presumably the one who is orchestrating queue policy and determining whether or not to call SendRequest again.
Have the caller check the session object for validity and decide whether to keep going based on that.
Additionally, I'm unfamiliar with that particular library, but briefly glancing at the documentation it looks like there's also a SendRequestAndWait() method with the same signature and that sounds like it might better meet your needs.
I have some code, and I have noticed it makes my app freeze. I'm looking for a solution that is better than mine.
How to wait for values which I don't know when I receive and I can't continue until I get them and only solution I figured up was using while until I receive those values.
I'm looking for better solution. The best if it wouldn't freeze my app. It has been told me I should use events, but I couldn't figure out how to do that.
IsBusy = true;
do
{
if (IsBusy)
{
//waiting for values which i don't know when i receive
//i can receive those values in 1sec and also in 2 min
if done -> IsBusy = false;
}
Thread.Sleep(2000);
} while (IsBusy);
IsBusy = true;
do
{
if (IsBusy)
{
//waiting for similar thing until i receive it
if done -> IsBusy = false;
}
Thread.Sleep(5000);
} while (IsBusy);
I think best way to use async await. In C#, asynchronous programming with async await is very easy. Code looks like synchronous.
private async void StartButtonClick(object sender, RoutedEventArgs e)
{
// Starting new task, function stops
// the rest of the function is set to cont
// UI not blocked
Task.Run(async () =>
{
var MyValue = await doSomethingAsync();
}); //there you waiting value
//continue code
}
There may be a couple possibilities, though the description of what you're waiting on is vague enough we may not be able to point you in a specific direction. Some things that might work are:
Event-based coding. If you can change the code of the process you're waiting for, you can have it raise an event that your calling code then handles. This other SO answer has a simple, complete C# program that raises and handles events.
BackgroundWorker often works well in Windows Forms projects, in my experience. In my experience it's one of the simpler ways to get started with multithreading. There's a highly-rated tutorial with code samples here that may help.
There are other ways to multithread your code, too (so that it doesn't "freeze up" while you're waiting), but these may be a simpler starting point for doing what you need.
Async/await may work for you, but I find they're most useful when you already have an existing doSomethingAsync()-type method to work with (such as async web/WCF service methods in a .NET-generated proxy). But if all the code's your own and you're trying to multithread from scratch, they won't be the central mechanism you'd use to get started. (Of course, if it turns out you are waiting on something with a built-in ...Async() method like a web service call, by all means use async/await, and please select #Astemir-Almov's as the accepted answer!)
[This appears to be a loooong question but I have tried to make it as clear as possible. Please have patience and help me...]
I have written a test class which supports an Async operation. That operation does nothing but reports 4 numbers:
class AsyncDemoUsingAsyncOperations
{
AsyncOperation asyncOp;
bool isBusy;
void NotifyStarted () {
isBusy = true;
Started (this, new EventArgs ());
}
void NotifyStopped () {
isBusy = false;
Stopped (this, new EventArgs ());
}
public void Start () {
if (isBusy)
throw new InvalidOperationException ("Already working you moron...");
asyncOp = AsyncOperationManager.CreateOperation (null);
ThreadPool.QueueUserWorkItem (new WaitCallback (StartOperation));
}
public event EventHandler Started = delegate { };
public event EventHandler Stopped = delegate { };
public event EventHandler<NewNumberEventArgs> NewNumber = delegate { };
private void StartOperation (object state) {
asyncOp.Post (args => NotifyStarted (), null);
for (int i = 1; i < 5; i++)
asyncOp.Post (args => NewNumber (this, args as NewNumberEventArgs), new NewNumberEventArgs (i));
asyncOp.Post (args => NotifyStopped (), null);
}
}
class NewNumberEventArgs: EventArgs
{
public int Num { get; private set; }
public NewNumberEventArgs (int num) {
Num = num;
}
}
Then I wrote 2 test programs; one as console app and another as windows form app. Windows form app works as expected when I call Start repeatedly:
But console app has hard time ensuring the order:
Since I am working on class library, I have to ensure that my library works correctly in all app models (Haven't tested in ASP.NET app yet). So I have following questions:
I have tested enough times and it appears to be working but is it OK to assume above code will always work in windows form app?
Whats the reason it (order) doesn't work correctly in console app? How can I fix it?
Not much experienced with ASP.NET. Will the order work in ASP.NET app?
[EDIT: Test stubs can be seen here if that helps.]
Unless I am missing something then given the code above I believe there is no way of guaranteeing the order of execution. I have never used the AsyncOperation and AsyncOperationManager class but I looked in reflector and as could be assumed AsyncOperation.Post uses the thread pool to execute the given code asynchronously.
This means that in the example you have provided 4 tasks will be queued to the thread pool synchronously in very quick succession. The thread pool will then dequeue the tasks in FIFO order (first in first out) but it's entirely possible for one of later threads to be scheduled before an earlier one or one of the later threads to complete before an earlier thread has completed its work.
Therefore given what you have there is no way to control the order in the way you desire. There are ways to do this, a good place to look is this article on MSDN.
http://msdn.microsoft.com/en-us/magazine/dd419664.aspx
I use a Queue you can then Enqueue stuff and Dequeue stuff in the correct order. This solved this problem for me.
The documentation for AsyncOperation.Post states:
Console applications do not synchronize the execution of Post calls. This can cause ProgressChanged events to be raised out of order. If you wish to have serialized execution of Post calls, implement and install a System.Threading.SynchronizationContext class.
I think this is the exact behavior you’re seeing. Basically, if the code that wants to subscribe to notifications from your asynchronous event wants to receive the updates in order, it must ensure that there is a synchronization context installed and that your AsyncOperationManager.CreateOperation() call is run inside of that context. If the code consuming the asynchronous events doesn’t care about receiving them in the correct order, it simply needs to avoid installing a synchronization context which will result in the “default” context being used (which just queues calls directly to the threadpool which may execute them in any order it wants to).
In the GUI version of your application, if you call your API from a UI thread, you will automatically have a synchronization context. This context is wired up to use the UI’s message queueing system which guarantees that posted messages are processed in order and serially (i.e., not concurrently).
In a Console application, unless if you manually install your own synchronization context, you will be using the default, non-synchronizing threadpool version. I am not exactly sure, but I don’t think that .net makes installing a serializing synchronization context very easy to do. I just use Nito.AsyncEx.AsyncContext from the Nito.AsyncEx nuget package to do that for me. Basically, if you call Nito.AsyncEx.AsyncContext.Run(MyMethod), it will capture the current thread and run an event loop with MyMethod as the first “handler” in that event loop. If MyMethod calls something that creates an AsyncOperation, that operation increments an “ongoing operations” counter and that loop will continue until the operation is completed via AsyncOperation.PostOperationCompleted or AsyncOperation.OperationCompleted. Just like the synchronization context provided by a UI thread, AsyncContext will queue posts from AsyncOperation.Post() in the order it receives them and run them serially in its event loop.
Here is an example of how to use AsyncContext with your demo asynchronous operation:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Starting SynchronizationContext");
Nito.AsyncEx.AsyncContext.Run(Run);
Console.WriteLine("SynchronizationContext finished");
}
// This method is run like it is a UI callback. I.e., it has a
// single-threaded event-loop-based synchronization context which
// processes asynchronous callbacks.
static Task Run()
{
var remainingTasks = new Queue<Action>();
Action startNextTask = () =>
{
if (remainingTasks.Any())
remainingTasks.Dequeue()();
};
foreach (var i in Enumerable.Range(0, 4))
{
remainingTasks.Enqueue(
() =>
{
var demoOperation = new AsyncDemoUsingAsyncOperations();
demoOperation.Started += (sender, e) => Console.WriteLine("Started");
demoOperation.NewNumber += (sender, e) => Console.WriteLine($"Received number {e.Num}");
demoOperation.Stopped += (sender, e) =>
{
// The AsyncDemoUsingAsyncOperation has a bug where it fails to call
// AsyncOperation.OperationCompleted(). Do that for it. If we don’t,
// the AsyncContext will never exit because there are outstanding unfinished
// asynchronous operations.
((AsyncOperation)typeof(AsyncDemoUsingAsyncOperations).GetField("asyncOp", BindingFlags.NonPublic|BindingFlags.Instance).GetValue(demoOperation)).OperationCompleted();
Console.WriteLine("Stopped");
// Start the next task.
startNextTask();
};
demoOperation.Start();
});
}
// Start the first one.
startNextTask();
// AsyncContext requires us to return a Task because that is its
// normal use case.
return Nito.AsyncEx.TaskConstants.Completed;
}
}
With output:
Starting SynchronizationContext
Started
Received number 1
Received number 2
Received number 3
Received number 4
Stopped
Started
Received number 1
Received number 2
Received number 3
Received number 4
Stopped
Started
Received number 1
Received number 2
Received number 3
Received number 4
Stopped
Started
Received number 1
Received number 2
Received number 3
Received number 4
Stopped
SynchronizationContext finished
Note that in my example code I work around a bug in AsyncDemoUsingAsyncOperations which you should probably fix: when your operation stops, you never call AsyncOperation.OperationCompleted or AsyncOperation.PostOperationCompleted. This causes AsyncContext.Run() to hang forever because it is waiting for the outstanding operations to complete. You should make sure that your asynchronous operations complete—even in error cases. Otherwise you might run into similar issues elsewhere.
Also, my demo code, to imitate the output you showed in the winforms and console example, waits for each operation to finish before starting the next one. That kind of defeats the point of asynchronous coding. You can probably tell that my code could be greatly simplified by starting all four tasks at once. Each individual task would receive its callbacks in the correct order, but they would all make progress concurrently.
Recommendation
Because of how AsyncOperation seems to work and how it is intended to be used, it is the responsibility of the caller of an asynchronous API that uses this pattern to decide if it wants to receive events in order or not. If you are going to use AsyncOperation, you should document that the asynchronous events will only be received in order by the caller if the caller has a synchronization context that enforces serialization and suggest that the caller call your API on either a UI thread or in something like AsyncContext.Run(). If you try to use synchronization primitives and whatnot inside of the delegate you call with AsyncOperation.Post(), you could end up putting threadpool threads in a sleeping state which is a bad thing when considering performance and is completely redundant/wasteful when the caller of your API has properly set up a synchronization context already. This also enables the caller to decide that, if it is fine with receiving things out of order, that it is willing to process events concurrently and out of order. That may even enable speedup depending on what you’re doing. Or you might even decide to put something like a sequence number in your NewNumberEventArgs in case the caller wants both concurrency and still needs to be able to assemble the events into order at some point.
I'm trying to do some async stuff in a webservice method. Let say I have the following API call: http://www.example.com/api.asmx
and the method is called GetProducts().
I this GetProducts methods, I do some stuff (eg. get data from database) then just before i return the result, I want to do some async stuff (eg. send me an email).
So this is what I did.
[WebMethod(Description = "Bal blah blah.")]
public IList<Product> GetProducts()
{
// Blah blah blah ..
// Get data from DB .. hi DB!
// var myData = .......
// Moar clbuttic blahs :) (yes, google for clbuttic if you don't know what that is)
// Ok .. now send me an email for no particular reason, but to prove that async stuff works.
var myObject = new MyObject();
myObject.SendDataAsync();
// Ok, now return the result.
return myData;
}
}
public class TrackingCode
{
public void SendDataAsync()
{
var backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += BackgroundWorker_DoWork;
backgroundWorker.RunWorkerAsync();
//System.Threading.Thread.Sleep(1000 * 20);
}
private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
SendEmail();
}
}
Now, when I run this code the email is never sent. If I uncomment out the Thread.Sleep .. then the email is sent.
So ... why is it that the background worker thread is torn down? is it dependant on the parent thread? Is this the wrong way I should be doing background or forked threading, in asp.net web apps?
BackgroundWorker is useful when you need to synchronize back to (for example) a UI* thread, eg for affinity reasons. In this case, it would seem that simply using ThreadPool would be more than adequate (and much simpler). If you have high volumes, then a producer/consumer queue may allow better throttling (so you don't drown in threads) - but I suspect ThreadPool will be fine here...
public void SendDataAsync()
{
ThreadPool.QueueUserWorkItem(delegate
{
SendEmail();
});
}
Also - I'm not quite sure what you want to achieve by sleeping? This will just tie up a thread (not using CPU, but doing no good either). Care to elaborate? It looks like you are pausing your actual web page (i.e. the Sleep happens on the web-page thread, not the e-mail thread). What are you trying to do here?
*=actually, it will use whatever sync-context is in place
Re producer/consumer; basically - it is just worth keeping some kind of throttle. At the simplest level, a Semaphore could be used (along with the regular ThreadPool) to limit things to a known amount of work (to avoid saturating the thread pool); but a producer/consumer queue would probably be more efficient and managed.
Jon Skeet has such a queue here (CustomThreadPool). I could probably write some notes about it if you wanted.
That said: if you are calling off to an external web-site, it is quite likely that you will have a lot of waits on network IO / completion ports; as such, you can have a slightly higher number of threads... obviously (by contrast) if the work was CPU-bound, there is no point having more threads than you have CPU cores.
It may torn down because after 20 seconds, that BackgroundWorker instance may be garbage collected because it has no references (gone out of scope).
Lets say I have a component called Tasking (that I cannot modify) which exposes a method “DoTask” that does some possibly lengthy calculations and returns the result in via an event TaskCompleted. Normally this is called in a windows form that the user closes after she gets the results.
In my particular scenario I need to associate some data (a database record) with the data returned in TaskCompleted and use that to update the database record.
I’ve investigated the use of AutoResetEvent to notify when the event is handled. The problem with that is AutoResetEvent.WaitOne() will block and the event handler will never get called. Normally AutoResetEvents is called be a separate thread, so I guess that means that the event handler is on the same thread as the method that calls.
Essentially I want to turn an asynchronous call, where the results are returned via an event, into a synchronous call (ie call DoSyncTask from another class) by blocking until the event is handled and the results placed in a location accessible to both the event handler and the method that called the method that started the async call.
public class SyncTask
{
TaskCompletedEventArgs data;
AutoResetEvent taskDone;
public SyncTask()
{
taskDone = new AutoResetEvent(false);
}
public string DoSyncTask(int latitude, int longitude)
{
Task t = new Task();
t.Completed = new TaskCompletedEventHandler(TaskCompleted);
t.DoTask(latitude, longitude);
taskDone.WaitOne(); // but something more like Application.DoEvents(); in WinForms.
taskDone.Reset();
return data.Street;
}
private void TaskCompleted(object sender, TaskCompletedEventArgs e)
{
data = e;
taskDone.Set(); //or some other mechanism to signal to DoSyncTask that the work is complete.
}
}
In a Windows App the following works correctly.
public class SyncTask
{
TaskCompletedEventArgs data;
public SyncTask()
{
taskDone = new AutoResetEvent(false);
}
public string DoSyncTask(int latitude, int longitude)
{
Task t = new Task();
t.Completed = new TaskCompletedEventHandler(TaskCompleted);
t.DoTask(latitude, longitude);
while (data == null) Application.DoEvents();
return data.Street;
}
private void TaskCompleted(object sender, TaskCompletedEventArgs e)
{
data = e;
}
}
I just need to replicate that behaviour in a window service, where Application.Run isn’t called and the ApplicationContext object isn’t available.
I've had some trouble lately with making asynchronous calls and events at threads and returning them to the main thread.
I used SynchronizationContext to keep track of things. The (pseudo)code below shows what is working for me at the moment.
SynchronizationContext context;
void start()
{
//First store the current context
//to call back to it later
context = SynchronizationContext.Current;
//Start a thread and make it call
//the async method, for example:
Proxy.BeginCodeLookup(aVariable,
new AsyncCallback(LookupResult),
AsyncState);
//Now continue with what you were doing
//and let the lookup finish
}
void LookupResult(IAsyncResult result)
{
//when the async function is finished
//this method is called. It's on
//the same thread as the the caller,
//BeginCodeLookup in this case.
result.AsyncWaitHandle.WaitOne();
var LookupResult= Proxy.EndCodeLookup(result);
//The SynchronizationContext.Send method
//performs a callback to the thread of the
//context, in this case the main thread
context.Send(new SendOrPostCallback(OnLookupCompleted),
result.AsyncState);
}
void OnLookupCompleted(object state)
{
//now this code will be executed on the
//main thread.
}
I hope this helps, as it fixed the problem for me.
Maybe you could get DoSyncTask to start a timer object that checks for the value of your data variable at some appropriate interval. Once data has a value, you could then have another event fire to tell you that data now has a value (and shut the timer off of course).
Pretty ugly hack, but it could work... in theory.
Sorry, that's the best I can come up with half asleep. Time for bed...
I worked out a solution to the async to sync problem, at least using all .NET classes.
Link
It still doesn't work with COM. I suspect because of STA threading. The Event raised by the .NET component that hosts the COM OCX is never handled by my worker thread, so I get a deadlock on WaitOne().
someone else may appreciate the solution though :)
If Task is a WinForms component, it might be very aware of threading issues and Invoke the event handler on the main thread -- which seems to be what you're seeing.
So, it might be that it relies on a message pump happening or something. Application.Run has overloads that are for non-GUI apps. You might consider getting a thread to startup and pump to see if that fixes the issue.
I'd also recommend using Reflector to get a look at the source code of the component to figure out what it's doing.
You've almost got it. You need the DoTask method to run on a different thread so the WaitOne call won't prevent work from being done. Something like this:
Action<int, int> doTaskAction = t.DoTask;
doTaskAction.BeginInvoke(latitude, longitude, cb => doTaskAction.EndInvoke(cb), null);
taskDone.WaitOne();
My comment on Scott W's answer seems a little cryptic after I re-read it. So let me be more explicit:
while( !done )
{
taskDone.WaitOne( 200 );
Application.DoEvents();
}
The WaitOne( 200 ) will cause it to return control to your UI thread 5 times per second (you can adjust this as you wish). The DoEvents() call will flush the windows event queue (the one that handles all windows event handling like painting, etc.). Add two members to your class (one bool flag "done" in this example, and one return data "street" in your example).
That is the simplest way to get what you want done. (I have very similar code in an app of my own, so I know it works)
Your code is almost right... I just changed
t.DoTask(latitude, longitude);
for
new Thread(() => t.DoTask(latitude, longitude)).Start();
TaskCompleted will be executed in the same thread as DoTask does. This should work.