I'm at my wits end trying to solve this issue.
I have a function in a class as such
public class ReceiveData
{
Dataprovider provider = new DataProvider();
public void ResponseData()
{
foreach(string anItem in TheList)
{
// AllData function is declared in class DataProvider
string result = provider.AllData(anItem);
}
//do something
}
}
That's simple. However, what would I do if AllData function had to make async function calls to get data?
Meaning, say
public class DataProvider
{
MyServiceClient client = new MyServiceClient();
public string AllData (string myItem)
{
client.FormattedDataCompleted += new EventHandler<FormattedDataCompletedEventArgs>(client_FormattedDataCompleted);
client.FormattedDataAsync(myItem);
}
void client_FormattedDataCompleted(object sender, FormattedDataCompletedEventArgs e)
{
// here's where the response comes back.
}
As you can see, now I cant simply call AllData function and directly get data back.
So, what would I have to do in ResponseData function to make sure I call the AllItem function, and get data back from the callback. Notice that there's a loop in that function, so I need to all the parameters I have sent through the loop gets respective response.
One approach I tried was by using AutoResetEvent class.
I defined a handler for this as
AutoResetEvent handle = new AutoResetHandle(false);
then I add handle.WaitOne() right after the async call. and on the callback, added handle.Set();
However, the applications get stuck at handle.WaitOne(). So I can't really see why that happens.
I now have a theoritical idea to see if I could have a event raiser on the callback, and an eventlistener in RecieveData class, and if those two communicate, I could get the data. But I've spent some time trying to learn more about event handlers, but haven't gotten the hang of it.
So does anybody have any other approach, ideas? Thanks!
Welcome to the asynchronous model. You have to re-think how you call methods when you go multithreaded.
You have some options:
Split the method in which you're making the call into two halves; in the first half, call AllData, do ANYTHING else you can possibly do without having the response object, and then exit your current method. When the async call completes, it'll call your handler, where you should perform all operations from the original method that require the response.
In the event handler for the async call completion, set a property that indicates the call is completed, and put the data out on a property somewhere as well. In the function that kicks off the call, at the point where you simply cannot continue execution until the call completes, wait in a while loop for the call to complete by polling the property and breaking once it indicates the call has been completed (you'll probably want a Thread.Yield() in the loop as well that you'll call when you haven't gotten a response yet, to make sure you aren't blocking other threads doing more important things than waiting)
Wrap your asynchronous call in a class that exposes a synchronous method. The wrapper class will have similar logic as integrating the async call into your method. It will make the call, wait for the response, and return that response as if it were a normal synchronous method call.
Remember that the asynchronous call is giving your calling thread the opportunity to do other work while the call is performed. Take full advantage of this if at all possible.
You just need to use a delegate and call BeginInvoke. You can then set a callback method to capture the result of the delegate call.
public class ReceiveData
{
private List<string> TheList = new List<string>
{
"1", "2", "3"
};
dynamic provider = new ExpandoObject();
public void ResponseData()
{
foreach (string anItem in TheList)
{
// AllData function is declared in class DataProvider
Func<string, string> asyncAllData = provider.AllData;
asyncAllData.BeginInvoke(anItem, AllDataDone, null);
}
//do something
}
private void AllDataDone(IAsyncResult iar)
{
AsyncResult ar = (AsyncResult)iar;
var del = (Func<string, string>)ar.AsyncDelegate;
// here's your result
string result = del.EndInvoke(iar);
}
}
Related
I am trying to call a REST service using RESTSharp and continuing execution immediately as I just need a task started but need to continue execution immediately so I am trying to use ExecuteAsync instead of Execute.
My code should look like this now
IRestResponse<ExpandoObject> restResponse = client.ExecuteAsync<ExpandoObject>(restRequest, response =>
{
callback(response.Content);
});
However, I have no idea how to implement the callback function and all samples don't show it. I assume it is like this but it does not compile.
private IRestResponse<ExpandoObject> callback(string content)
{
return null;
}
Any ideas?
There are a few ways to implement what you're trying to do, but the it looks like your
callback has wrong method signature...to get something "basic" running, the following should work
(I added wait simply for testing):
EventWaitHandle resetEvent = new AutoResetEvent(false);
client.ExecuteAsync(request, response =>
{
callback(response.Content);
resetEvent.Set();
return;
});
resetEvent.WaitOne();
}
private static void callback(string content)
{
System.Console.WriteLine(content);
}
What I would like to do is:
Call a function (DoWork) which as part of it's work will subscribe to multiple hot inputs through multiple Worker classes
Before calling the function subscribe to all the updates that DoWork subscribes to
Once finished, dispose of all the subscriptions
It is probable that at least one incoming event will fire before DoWork has completed.
Questions:
Are Subjects the correct way to do this? It feels like there should be a better way?
How to ensure that once the subscription in Main is disposed, all of the incomingX subscriptions are also disposed - i.e. Main should control the lifecycle of all the subscriptions.
void Main()
{
var worker = new Worker();
using (worker.UpdateEvents.Subscribe(x => Console.WriteLine()))
{
worker.DoWork();
}
}
public class Worker1
{
private readonly Subject<string> updateEvents = new Subject<string>();
public IObservable<string> UpdateEvents { get { return updateEvents; } }
public void DoWork()
{
// Do some work
// subscribe to a hot observable (events coming in over the network)
incoming1.Subscribe(updateEvents);
var worker2 = new Worker2();
worker2.UpdateEvents.Subscribe(updateEvents);
worker2.DoWork();
}
}
public class Worker2
{
private readonly Subject<string> updateEvents = new Subject<string>();
public IObservable<string> UpdateEvents { get { return updateEvents; } }
public void DoWork()
{
// Do some work
// subscribe to some more events
incoming2.Subscribe(updateEvents);
var workerN = new WorkerN();
workerN.UpdateEvents.Subscribe(updateEvents);
workerN.DoWork();
}
}
James's answer (use Subject and Merge) captures the essence of the question. This answer offers a pattern that I've found useful in this situation (based on your comments to James's answer).
Essentially the pattern is to have your worker's expose an IObservable that the caller will subscribe to before calling DoWork. But this sort of API (call A before calling B) is problematic because it introduces temporal coupling.
To eliminate the temporal coupling, you end up turning your worker itself into an cold Observable that implicitly calls DoWork when the caller subscribes. Once you realize the power of cold observables and the ability to use Observable.Create to take action when an observer subscribes, the sky's the limit on the Rx chains you can create without ever needing to reach for a Subject. Here's an example based on your original code.
Worker is simple. It just subscribes to incoming1 and to Worker2.
Worker2 is slightly more complex. It subscribes to incoming2, performs some additional work, then finally subscribes to WorkerN.
All the while maintaining the correct OnError, OnCompleted logic which your original code example fails to do. Meaning that the observable stream that Main sees does not Complete until all of the incoming streams and work streams complete. But Main fails as soon as any of the incoming streams or work streams fails. Your code example with multiple calls to Subscribe(someSubject) would cause the Subject to complete (and thus Main's incoming stream to complete) as soon as any of the incoming streams completes.
public class Worker1
{
public IObservable<string> UpdateEvents { get; private set; };
public Worker1()
{
// Each time someone subscribes, create a new worker2 and subscribe to the hot events as well as whatever worker2 produces.
UpdateEvents = Observable.Create(observer =>
{
var worker2 = new Worker2();
return incoming1.Merge(worker2.UpdateEvents).Subscribe(observer);
});
}
}
public class Worker2
{
public IObservable<string> UpdateEvents { get; private set; };
public Worker2()
{
// Each time someone subscribes, create a new worker and subscribe to the hot events as well as whatever worker2 produces.
UpdateEvents = Observable.Create(observer =>
{
// maybe this version needs to do some stuff after it has subscribed to incoming2 but before it subscribes to workerN:
var doWorkThenSubscribeToWorker = Observable.Create(o =>
{
DoWork(o);
var worker = new WorkerN();
return worker.UpdateEvents.Subscribe(o);
}
return incoming2.Merge(doWorkThenSubscribeToWorker).Subscribe(observer);
});
}
private void DoWork(IObserver<string> observer)
{
// do some work
observer.OnNext("result of work");
}
}
void Main()
{
var worker = new Worker();
worker.UpdateEvents.Do(x => Console.WriteLine()).Wait();
}
It's hard to follow exactly what you are asking for - a small but complete program would help here I think.
That said, there's nothing wrong with using a Subject to introduce input into the Rx pipeline - there's a lot written about that on StackOverflow and elsewhere, so I won't rehash it.
Going just by the title of your question, I wonder does the following suit your purpose?
Combining a dynamic number of streams
To do this you can use Merge on a stream of streams. Your streams must all be of the same type - if they are not, you can create a suitable container type and project them into that type using Select. For simplicity, I will assume the unified type is long.
To start create a container for the streams:
var container = new Subject<IObservable<long>>();
Then combine the contained streams:
var combined = container.Merge();
Subscribe to combined to consume the results in the usual way, and dispose the subscription to unsubscribe from all streams at once.
You can then add streams as they are created like this:
// assume we got this from somewhere - e.g. a "worker" factory function
// Observable.Create may well be helpful to create an observable
// that initiates getting data from a network connection upon its subscription
IObservable<long> someNewStream;
// add the someNewStream to the container (it will be subscribed to once added)
container.OnNext(someNewStream);
Example use
// dump out the combined results to the console,
// IRL you would subscribe to this to process the results
var subscription = combined.Subscribe(Console.WriteLine);
// add a stream of longs
container.OnNext(Observable.Interval(TimeSpan.FromSeconds(1)));
Console.WriteLine("Stream 1 added");
Console.ReadLine();
// add another stream
container.OnNext(Observable.Interval(TimeSpan.FromSeconds(1)));
Console.WriteLine("Step 2");
Console.ReadLine();
// this will unsubscribe from all the live streams
subscription.Dispose();
I am using WCF Async methods.
I face issue when I try to return the value of the callback function.
What are the possible methods of solution? (using .net 4.0, but not 4.5)
public static Object LoadInfo()
{
var service = new SomeWcfService();
service.BeginGetInfo(CallbackMethod, service);
// HOW TO GET INFROMATION FROM CALLBACK??
return INFORMATION;
}
private static void CallbackMethod(IAsyncResult ar)
{
// HOW TO PASS INFROMATION TO LoadInfo??
var INFORMATION = (ar.AsyncState as SomeWcfService).EndGetInfo(ar);
}
Note: All work should be asynchronously.
Thanks.
Better you design to use the async pattern than fight against it.
But, if you must access an async method synchronously, you can use a semaphore to block the calling thread until the async method returns.
public static Object LoadInfo()
{
// this is our semaphore
var blocker = new AutoResetEvent();
object result = null;
var service = new SomeWcfService();
// use a lambda instead of a method as the callback.
// this will result in a closure where we can access the result and blocker variables
service.BeginGetInfo(x =>
{
// We are on a different thread within this lambda
result = (x.AsyncState as SomeWcfService).EndGetInfo(ar);
// release anybody calling blocker.WaitOne
blocker.Set();
}, service);
// we are still on the original thread here, and
// BeginGetInfo has possibly not yet executed, so we must wait until Set is called
blocker.WaitOne(Timeout.Infinite);
return result;
}
This is rarely a good design choice. Aynchornous patterns are much better for responsive UI. Better to do something like this
public void LoadInfo()
{
// Makes the UI show a loading indicator, blocking all actions except for CANCEL
LoadingInfo = true;
var service = new SomeWcfService();
service.BeginGetInfo(CallbackMethod, service);
}
private void CallbackMethod(IAsyncResult ar)
{
// the UI is now released from loading
LoadingInfo = false;
// the UI is triggered to show our data
ViewModel.Data = (ar.AsyncState as SomeWcfService).EndGetInfo(ar);
}
Understanding async at first, especially with callbacks is tough. In your example you make an incorrect, but natural assumption...
public static Object LoadInfo()
{
var service = new SomeWcfService();
service.BeginGetInfo(CallbackMethod, service);
// HOW TO GET INFROMATION FROM CALLBACK??
// ERROR: You assume you have more work to do in this method,
// or that this is the place to return your results.
return INFORMATION;
}
The method you give below, is where the work occurs after your results are returned:
private static void CallbackMethod(IAsyncResult ar)
{
// HOW TO PASS INFROMATION TO LoadInfo??
// OOPS! No need to pass pack to LoadInfo - it's done...
var INFORMATION = (ar.AsyncState as SomeWcfService).EndGetInfo(ar);
}
Instead you will want something like this
public static void LoadInfo()
{
var service = new SomeWcfService();
// begin an asynchronous service call
// and handle the results in another method, "CallbackMethod"
service.BeginGetInfo(CallbackMethod, service);
// You can do other, non-service related,
// things here while the service call executes
}
Then your other method handles all the results:
private static void CallbackMethod(IAsyncResult ar)
{
var results = (ar.AsyncState as SomeWcfService).EndGetInfo(ar);
// Do whetever you need with results here
}
As Will pointed out in his excelent answer (+1, as if he needs it lol!), instead of having a separate call-back method, you can use an anonymous method with a lambda expression like:
public static void LoadInfo()
{
var service = new SomeWcfService();
// begin an asynchronous service call
// and handle the results in this anonymous method
service.BeginGetInfo(x =>
{
// B. This code block will be called when the service returns with results
var results = (ar.AsyncState as SomeWcfService).EndGetInfo(ar);
// Do whetever you need with results here
}, service);
// A. You can do other things here while the service call executes
// but debugging this gets more complicated because things will likely
// occur at A before they occur at B
}
So, the over-all mentality of Asynchronous is:
Your program sets up and begins a service call then keeps doing whatever else it wants, without waiting. Hint: This is a natural place to start a loading animation, and/or disable some controls.
When you made the async call, you gave, as one of your parameters, a method to run once the call is complete.
When the service returns with results, the method you specified is run to do work on the results. Hint: In this method, you can end the loading animation, and/or re-enable your controls, and plug the results into your ViewModel.
I have a method like this:
public IOrganizationService GetConnection(bool multi)
{
if(!multi)
{
Parallel.For(0, 1, i =>
{
dynamic _serviceobject= InitializeCRMService();
});
}
else
{
ThreadPool.QueueUserWorkItem
(
new WaitCallback
(
(_) =>
{
dynamic _serviceobject= InitializeCRMService();
}
)
);
}
}
I want to return the _serviceobject *directly* from inside the method.Will returing it twice i.e once from if and once from the else loop solve my problem.Please note I am using Multithreading using the concept of Pool threading.Will the _serviceobjects stay unique in case two threads are running parallely.I do not wan't any interaction to happen between my threads.
The code inside of WaitCallback will execute in the thread pool, and will do so probably after GetConnection has returned (that's the point of doing asynchronous operations). So, since it is another thread (with another call stack) and it will potentially execute after GetConnection has returned, you cannot make GetConnection return from inside of WaitCallback. If you really want to do that, then you will have to make GetConnection wait until WaitCallback has completed execution. ManualResetEvent can do the trick:
public IOrganizationService GetConnection(bool multi)
{
var waitHandle = new ManualResetEvent(false);
dynamic result = null;
if(!multi)
{
Parallel.For(0, 1, i =>
{
result = InitializeCRMService();
waitHandle.Set();
});
}
else
{
ThreadPool.QueueUserWorkItem
(
new WaitCallback
(
(_) =>
{
result = InitializeCRMService();
waitHandle.Set();
}
)
);
}
//We wait until the job is done...
waitHandle.WaitOne();
return result as IOrganizationService; //Or use an adecuate casting
}
But doing this defies the point of having asynchronous operations in the first place. Since the caller thread will have to wait until the job is done in another thread, sitting there, doing nothing... Then, why don't just do it synchrnously? In a word: Pointless.
The problems is that returning the value directly is a synchronous API. If you want asyncrhonous operations, you will want an asycrhonous API. If you will have an asynchronous API then you are going to have to change the way the caller works.
Solutions include:
Having a public property to access the reuslt (option 1)
Having a callback (option 2)
resourcing to events
Returning a Task (or use the async keywork if available)
Returning IObservable (using Reactive Extensions if available)
Notes:
Having a puplic property means you will need to deal with syncrhonization in the caller.
Having a callback, means an odd way to call the method and no explicit way to wait.
Using events has the risk of the caller staying subscribed to the event handler.
Returning a Task seems like an overkill since you are using the thread pool.
Using IObservable without Reactive Extension is prone to error, and much more work compared to the alternatives.
Personally I would go for the callback option:
public void GetConnection(bool multi, Action<IOrganizationService> callback)
{
if (ReferenceEquals(callback, null))
{
throw new ArgumentNullException("callback");
}
if(!multi)
{
Parallel.For(0, 1, i =>
{
callback(InitializeCRMService() as IOrganizationService);
//Or instead of using "as", use an adecuate casting
});
}
else
{
ThreadPool.QueueUserWorkItem
(
new WaitCallback
(
(_) =>
{
callback(InitializeCRMService() as IOrganizationService);
//Or instead of using "as", use an adecuate casting
}
)
);
}
}
The caller then does something like this:
GetConnection
(
false,
(seriveObject) =>
{
/* do something with seriveObject here */
}
);
//Remember, even after GetConnection completed seriveObject may not be ready
// That's because it is asyncrhonous: you want to say "hey Bob do this for me"
// and you can go do something else
// after a while Bob comes back an says:
// "that thing you asked me to do? well here is the result".
// We call that a callback, and the point is that you didn't have to wait for Bob
// you just kept doing your stuff...
//So... when is seriveObject ready? I don't know.
//But when seriveObject is ready the callback will run and then you can use it
You cannot return it from inside the WaitCallback handler because there's no one in your code to return it to. That's just a callback.
You may want to try defining a custom event (derived from EventArgs) which has a dynamic member.
Then you can raise this event from your worker entry point and also send with it the dynamic object.
You can bind to the event where needed (i.e. where you want to use the dynamic object).
EDIT (to also show some code):
In the same class where you have your GetConnection method, also define an event:
internal event EventHandler<SomeEventArgs> OnWorkerFinished = (s, e) => {};
then, define somewhere in your project (close to this class), the SomeEventArgs class:
internal class SomeEventArgs : EventArgs
{
public dynamic WorkerResult { get; private set; }
public SomeEventArgs(dynamic workerResult)
{
WorkerResult = workerResult;
}
}
Next, in the worker:
new WaitCallback
(
(_) =>
{
dynamic _serviceobject= InitializeCRMService();
//Here raise the event
SomeEventArgs e = new SomeEventArgs(_serviceObject);
OnWorkerFinished(this, e);
}
)
I don't know where you want to use get the result, but in that place you should bind to the OnWorkerFinished event of this class (in which you have the GetConnectionMethod).
I have a Silverlight class library that references a WCF service,
I have a method called StoreNodes() that call the WCF service.
like this:
public void StoreNodes()
{
DataServiceClient client = new DataServiceClient();
client.GetNodesForCoreCompleted += client_GetNodesForCoreCompleted;
client.GetNodesForCoreAsync();
}
and another method called BuildAll() like this:
public void BuildAll()
{
StoreNodes();
Method2();
}
My problem is method2() is not a WCF service, and the both StoreNodes and Method2 have some variables in common, these variables get their values in StoreNodes and the second method do some operation on them, anyway, the problem is the methode2 is executed before the first method finishes, so I got the null reference error. How can I make sure that the second method is executed after the service calling is finished??
I hope I made my question clear.
Something along these lines should work:
public void BuildAll()
{
StoreNodes(() => { Method2(); });
}
public void StoreNodes(Action getNodesCompleteAction)
{
DataServiceClient client = new DataServiceClient();
client.GetNodesForCoreCompleted += (sender, e) => {
// your handler code
// call Method2() Action wrapper
getNodesCompleteAction();
}
client.GetNodesForCoreAsync();
}
There are two ways that you could solve this problem.
First, you can set up a type of async method chaining. After each method completes, it calls the next one:
StoreNodes();
|
V
client_GetNodesForCoreCompleted
|->Method2();
And, you could continue this...
|
V
client_Method2Completed
|->Method3();
....
The other way is that you could put some sort of wait inside of Method2 that will wait until the appropriate variables are set. However, this is against the general programming paradigm of Silverlight, so I would not suggest it realistically. It would lock your UI while you simply wait for a resource. IF, this is what you want, then here is a SO answer on how you could wait for the values