I have the following two methods:
private static void webservicecalls()
{
WebServiceOne();
WebServiceTwo();
}
So how i can call these two methods asynchronously instead of waiting for the first web service call to be complete before calling the second web service?
Update:
Now both WebSericeOne and WebServiceTwo have sub calls such as:
private static void WebServiceOne()
{
CallOne();
CallThree();
}
private static void WebServiceTwo()
{
CallTwo();
CallFour();
}
so i need the call to have the following sequence for the sub calls :-
CallOne();
CallTwo();
CallThree();
CallFour();
Depending on what are you using to implement webserviceone webservicetwo, it is quite likely that the web-service tooling itself will have full async support, so the first thing to do is: check that, and use the async API rather than the sync API.
If, for some reason, that does not exist - you could do something like:
var task = new Task(() => webservice1());
task.Start();
webservice2();
task.Wait();
(obviously you could run both fully async; I'm assuming in the above you just want to run them both in parallel, and "join" at the end)
Re your edit: if the order must be exactly "one","two","three","four", then you can't do them in parallel, so you would have to instead just run the entire thing in the background:
new Task(() => {
webservice1();
webservice2();
}).Start();
which will guarantee the execution order, sacrificing parallelism.
Action one = () => WebServiceOne();
Action two = () => WebServiceTwo();
one.BeginInvoke(null, null);
two.BeginInvoke(null, null);
I like using an Action.
private static void WebServiceCalls()
{
var someState = 3;
Action a1 = () => { WebserviceOne(); };
Action a2 = () => { WebserviceTwo(); };
a1.BeginInvoke(WebServiceCallBack, someState); //see code section below
a2.BeginInvoke(null, null); //fire and forget...
}
This also allows you to create a Callback for handling code:
void WebServiceCallBack(IAsyncResult result)
{
int state = (int)result.AsyncState;
//do more??
}
#Mark brings up a valid point: If you are working with a webservice within Visual studio, you can use the service reference configuration window to create the Channel Proxy class with async syntax. (I.e. with the BeginWebServiceOne and EndWebServiceOne which would preclude the need to create Async wrappers.)
Take a look at the task library here, and the navigation for the sub categories on the left
http://msdn.microsoft.com/en-us/library/dd537609.aspx
Related
I want to test the Save() method which is residing inside the Contributor class. This method, in turn, opens a dialog which, when finished loading, actions an event that triggers the method that I want to mock - PushToPortal.
internal class Contributor
{
private readonly IEntryPointWrapper _entryPoint;
private readonly ISyncDialog _dialog;
public event Action OnPushToWeldCompleted;
internal void Save(Document document)
{
...
void Ptp() => PushToPortal(information);
_dialog.ShowDialog(Ptp);
}
}
When ShowDialog is called, OnLoadingCompleted += Ptp; is invoked.
The problem begins just here. PushToPortal looks like this:
internal virtual void PushToPortal(Information information)
{
var pushToPortal = Task.Run(() => {
var result = _entryPoint.ProcessElements(information);
});
pushToPortal.ContinueWith(task => OnPushToPortalCompleted?.Invoke(), TaskScheduler.FromCurrentSynchronizationContext());
}
Basically, when running the tests, they continue running while the async method is still processing and when asserting, the callback does not retrieve the needed information unless I use Thread.Sleep, which is not a solution that I'd like.
The working solution would be:
_entryPointMock.Setup(epm => epm.ProcessElements(It.IsAny<Information>()))
.Callback<WeldInformation>(information => actualWeldInformation = information)
.Returns(new InfoResult { Status = Status.Succeed, InfoCount = 1 });
Thread.Sleep(5000);
_contributor.Save(document);
I tried mocking the PushToPortal method and use a Callback to retrieve its arguments, without going into ProcessElements, but it does not seem to do anything at all.
_entryPointMock.Setup(epm => epm.ProcessElements(It.IsAny<Information>()))
.Returns(new InfoResult { Status = Status.Succeed, InfoCount = 1 });
var mock = new Mock<Contributor>();
mock.CallBase = true;
mock.Setup(x => x.PushToPortal(It.IsAny<Information>()))
.Callback<Information>(information => actualInformation = information);
_contributor.Save(document);
Therefore, how can I mock PushToPortal properly such that I retrieve the information, without actually entering the new thread which processes the elements? I am looking for a solution which does not imply changing the current code very much - an example which I thought of (and would not like to implement) would've been breaking down the functionality and returning a Task.
I noticed that I am able to get the data in the following two ways (reference OPTION 1 and OPTION 2) and wanted to know if there are any implications/benefits in picking one over the other? I am using .NET 4.5.1 and am loading data from an on-premise SQL Server using async/await.
// ***** OPTION 1 *****
// Constructor
public SomeViewModel(IProjectService projectService)
{
Task.Run(async () => await GetAllDataAsync());
}
// This method calls out all of the other local async/await methods to download the data
private async Task GetAllDataAsync()
{
await GetProjectDataAsync();
await GetAssignmentDataAsync();
... more await calls ...
}
// A typical method call to get data from service
private async Task GetProjectDataAsync()
{
var projects = await projectService.GetProjectsAsync();
this.ProjectList = projects;
}
// ***** OPTION 2 *****
// Constructor
// I call Task.Run() for all of the methods that download data
public SomeViewModel()
{
_service = service;
Task.Run(async () => await this.GetProjectDataAsync());
Task.Run(async () => await this.GetAssignmentDataAsync());
... more Task.Run() calls ...
}
// A typical method call to get data from service
private async Task GetProjectDataAsync()
{
var projects = await projectService.GetProjectsAsync();
this.ProjectList = projects;
}
EDIT 1:
Here is an example of the async/await method from my repository:
public async Task<IList<Project>> GetProjectsAsync()
{
using (Context ctx= new ProjectContext())
{
IEnumerable<Project> myProjects = ctx.Projects;
return await myProjects.ToListAsync();
}
}
EDIT 2:
I currently acquired the book, Concurrency in C# Cookbook, by Stephen Cleary and am looking for a suitable solution from the book in combination with the given advice here. Could anyone point me to certain section of the book that can assist me in my scenario, i.e. loading a lot of data from many tables that will be harnessed by an application?
EDIT 3:
// ***** OPTION 3 *****
// Constructor
public SomeViewModel()
{
_service = service;
DownloadData();
}
// A normal method that awaits async methods
private void DownloadData()
{
Task.Run(async () => await GetProjectDataAsync());
Task.Run(async () => await GetAssignmentDataAsync());
... more await calls to async Task methods that call services that in turn have async Task methods
}
I doubt any of these are suitable for your needs. Since a constructor can't be async there is no way to wait until the task you start are complete. You could call Task.Wait but that would annihilate all the benefits derived from async and you'd need to deal with the resulting deadlock.
Right now the tasks you start run concurrently with the rest of the request processing. This is probably racy and not what you wanted. If this ever worked it was by accident.
Move that code out of the ctor to an ordinary method and use await all the way through.
I want to start long-running operation like requesting a web page from ViewModel, and perform some progress-update operations on my View. Before, I easily achieved this by awaiting my Model's async methods, but in current project I'm restricted with .NET 4.0, so I can't use C#5 features.
What is the recommended way of doing this?
Use this -
Task.Factory.StartNew(() =>
{
// Code to load web page or any code you want to run asynchronously
}).ContinueWith(task =>
{
// Code you want to execute on completion of the above synchronous task,
}, UIHelper.GetUITaskScheduler());
wherein the UIHelper class has the following static method -
public class UIHelper
{
/* Some other methods */
public static TaskScheduler GetUITaskScheduler()
{
TaskScheduler scheduler = null;
Application.Current.Dispatcher.Invoke(() =>
{
scheduler = TaskScheduler.FromCurrentSynchronizationContext();
});
return scheduler;
}
}
use RX
https://rx.codeplex.com/
You can also observe on the SyncronizationContext.Current
Check them out...
I have the following simple method in C#:
private static void ExtendTaskInternal<U>(
ref U task_to_update, U replace, Action a) where U : Task
{
var current = Interlocked.Exchange(ref task_to_update, replace);
if (current == null)
Task.Run(a);
else
current.AppendAction(a);
}
This is used for the following methods:
//A Task can only run once. But sometimes we wanted to have a reference to some
//tasks that can be restarted. Of cause, in this case "restart" a task means
//replace the reference with a new one. To safely do so we have to ensure a
//lot of things:
//
// * Would the referee be null?
// * Is it still running?
// * The replacement of the task must be atomic
//
//This method can help solving the above issues. If `task_to_update` is null,
//a new Task will be created to replace it. If it is already there, a new Task
//will be created as its continuation, which will only run when the previous
//one finishes.
//
//This is looks like a async mutex, since if you assume `ExtendTask` is the only
//function in your code that updates `task_to_update`, the delegates you pass to
//it runs sequentially. But the difference is that since you have a reference to
//a Task, you can attach continuations that receive notification of lock
//releases.
public static Task<T> ExtendTask<T>(ref Task<T> task_to_update, Func<T> func)
{
var next_ts = new TaskCompletionSource<T>();
ExtendTaskInternal(ref task_to_update, next_ts.Task,
() => next_ts.SetResult(func()));
return next_ts.Task;
}
If you want to do something but only after something else have already been done, this is useful.
Now, this version can only used to replace a Task<T>, not a Task since ref variables are invariant. So if you want it to work for Task as well you have to duplicate the code:
public static Task<T> ExtendTask<T>(ref Task task_to_update, Func<T> func)
{
var next_ts = new TaskCompletionSource<T>();
ExtendTaskInternal(ref task_to_update, next_ts.Task,
() => next_ts.SetResult(func()));
return next_ts.Task;
}
And so you can implement another version that works on Actions.
public static Task ExtendTask(ref Task task_to_update, Action a)
{
return ExtendTask(ref task_to_update, () =>
{
a();
return true;
});
}
So far so good. But I don't like the first and the second version of the ExtendTask, since the body looks exactly the same.
Are there any way to eliminate the duplication?
Background
People ask why not use ContinueWith.
First, notice that AppendAction is just a wrapper function (from Microsoft.VisualStudio.Threading) of ContinueWith so this code is already using it indirectly.
Second, What I did differently here is that I have a reference to update, so this is another wrapper function to ContinueWith, the purpose of those functions is to make it easier to use in some scenarios.
I provide the following concrete example (untested) to illustrate the usage of those methods.
public class Cat {
private Task miuTask = null;
//you have to finish a miu to start another...
private void DoMiu(){
//... do what ever required to "miu".
}
public Task MiuAsync(){
return MyTaskExtension.ExtendTask(ref miuTask, DoMiu);
}
public void RegisterMiuListener(Action whenMiued){
var current = miuTask;
if(current==null) current = TplExtensions.CompletedTask();
current.AppendAction(whenMiued);
}
}
When invoking a WCF service asynchronous there seems to be two ways it can be done.
1.
WcfClient _client = new WcfClient();
public void One()
{
_client.BegindoSearch("input", ResultOne, null);
}
private void ResultOne(IAsyncResult ar)
{
string data = _client.EnddoSearch(ar);
}
2.
public void Two()
{
WcfClient client = new WcfClient();
client.doSearchCompleted += TwoCompleted;
client.doSearchAsync("input");
}
void TwoCompleted(object sender, doSearchCompletedEventArgs e)
{
string data = e.Result;
}
And with the new Task<T> class we have an easy third way by wrapping the synchronous operation in a task.
3.
public void Three()
{
WcfClient client = new WcfClient();
var task = Task<string>.Factory.StartNew(() => client.doSearch("input"));
string data = task.Result;
}
They all give you the ability to execute other code while you wait for the result, but I think Task<T> gives better control on what you execute before or after the result is retrieved.
Are there any advantages or disadvantages to using one over the other? Or scenarios where one way of doing it is more preferable?
I would not use the final version because it will run the operation on a worker thread instead of an I/O thread. This is especially bad if you're doing it inside ASP.NET, where the worker threads are needed to serve requests. Not to mention, you're still blocking on the main thread waiting for the task to finish when you check its Result, so technically you're wasting two worker threads, or one worker and the UI.
The BeginXYZ and XyzAsync methods for WCF clients work essentially the same way - you should choose the appropriate version based on the use case you want to support (either APC or event-driven, respectively). For example, the BeginXyz version would (perhaps counterintuitively) be easier to use within an ASP.NET (or MVC) async page, whereas the XyzAsync version would be easier to use in a Windows Form.
There's a problem with your first example. You should certainly not be creating a new WcfClient instance when you call EndDoSearch. You should either keep the original instance around in a field or pass it as the state parameter.
But in general, I prefer option #1 because it makes it very easy to use an anonymous method to handle the result.
var client = new WcfClient();
client.BeginDoSearch("input", ar => {
var result = client.EndDoSearch(ar);
// blah blah
}, null);