How to Calling the webservice without using the function service_GetItemInfoCompleted() in the below code?
Can it get the result without the function service_GetItemInfoCompleted().
Any idea?
private void btnFind_Click(object sender, RoutedEventArgs e)
{
Service1Client service = new Service1Client();
service.GetItemInfoAsync(txt1.Text);
service.GetItemInfoCompleted += new EventHandler<GetItemInfoCompletedEventArgs>(service_GetItemInfoCompleted);
}
void service_GetItemInfoCompleted(object sender, GetItemInfoCompletedEventArgs e)
{
txb1.Text = e.Result;
}
Example 2
public void running()
{
ServiceReference1.WebServiceSoapClient test = new ServiceReference1.WebServiceSoapClient();
test.ReadTotalOutstandingInvoiceCompleted += new EventHandler<ServiceReference1.ReadTotalOutstandingInvoiceCompletedEventArgs>(serviceClient);
test.ReadTotalOutstandingInvoiceAsync();
}
public void serviceClient(object sender, ReadTotalOutstandingInvoiceCompletedEventArgs e)
{
answer = int.parse(e.Result.ToString());
}
The above approach is the correct approach: Send the request to the service and when it returns, display the returned data in your textbox.
If you performed the same operation in one blocking call ...
private void btnFind_Click(object sender, RoutedEventArgs e)
{
Service1Client service = new Service1Client();
txtb1.Text = service.GetItemInfoAsync(txt1.Text);
}
... then your main UI thread would block until the data is returned from the service. If the service took several seconds to return, then your app's UI would 'hang' intermittently for several seconds, giving your users a very poor experience. This is a bad thing to do and something to avoid at all cost!
So we want to asynchronously call your service and wait for it to return without blocking threads. But rather than write the async code by hand, we can use the new async & await keywords in C# 5.0 to achieve the same goal as above but with less code & complexity:
private async void btnFind_Click(object sender, RoutedEventArgs e)
{
Service1Client service = new Service1Client();
string result = await service.GetItemInfoAsync(txt1.Text);
txtb1.Text = result;
}
Note the use of async and await in the code above. The async keyword tells the compiler that you want it to build a state-machine which is driven by await states. Each await keyword tells the compiler to add a new state to the state-machine. When the code is executed, the await code sets up the state-machine to pick-up at the next operation when the awaited-upon task (service.GetItemInfoAsync() in this case) completes.
HTH.
Related
I'm working on a plugin for .Net WPF application which uses the frame pushing technique to achieve 'responsible' UI. Each long-running task in its SDK calls the code:
public static void Wait(Task task)
{
DispatcherFrame nestedFrame = new DispatcherFrame();
task.ContinueWith(delegate { return nestedFrame.Continue = false; });
Dispatcher.PushFrame(nestedFrame);
task.Wait();
}
So the typical SDK's method can be emulated by the following code:
private void SdkMethod()
{
var t = Task.Factory.StartNew(() =>
{
Thread.Sleep(1500);
});
Wait(t);
}
It causes a situation when I can not do two synchronous calls to the SDK's methods from the UI thread:
private void OnClick(object sender, RoutedEventArgs e)
{
this.sdk.SdkMethod();
this.sdk.SdkMethod();
}
Is there any way to synchronize calls in such a situation? I cannot modify SDK, only my own calls to it.
If I understood correctly from reading the post and comments, you want to call SdkMethod and have it act synchronously. It's being called without letting you know when it is done.
If it is a void method and it isn't a task, you aren't going to get anything in return. I tried to listen to the Dispatcher Hooks for completion, but that was not helpful.
I'd create an aysnc Task method that has a Task.Delay then await it between calls. That way you aren't interrupting the user, but you still force the call to be paused until you call the second method.
private void OnClick(object sender, RoutedEventArgs e)
{
this.sdk.SdkMethod();
await DelayAsync(3).ConfigureAwait(false);
this.sdk.SdkMethod();
}
private async Task DelayAsync(int seconds)
{
await Task.Delay(seconds * 1000).ConfigureAwait(false);
}
I hope this helps.
I'm trying to open an OpenFileDialog within C# (codebehind, on an asp.net page). Because the regular references and the system.windows.form ones have some conflicts, I'm having to use the OpenFileDialog box within a thread, as below:
protected void Button1_Click(object sender, EventArgs e)
{
Thread newThread = new Thread(new ThreadStart(BrowseForFile));
newThread.SetApartmentState(ApartmentState.STA);
newThread.Start();
}
static void BrowseForFile()
{
System.Windows.Forms.OpenFileDialog MyFile = new System.Windows.Forms.OpenFileDialog();
if (MyFile.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
}
}
The way the page works means that this has to be in C# - using asp.net's fileupload won't work.
Now, the OpenFileDialog appears fine, and I can get values from it, but I ideally need to pass values into the thread (the BrowseForFile) and have it work with other controls on the page, in order to set things up. However, I'm very new to using threads.
Can someone show me, basically, how to get an integer from the Button1_Click into the BrowseForFile, and how I would set a label on the page from BrowseForFile?
If you use a modern version of .net you could use async-await for this. This makes it much easier for you to communicate with your dialog and to pass data to the thread that performs your background work.
To be able to use async-await:
Declare your function async
Let your function return Task instead of void and Task<TResult> instead of TResult.
There is one exception: event handlers may return void
In your async function start your other threads using Task.Run
while the other thread is running you can do other things
if you need the result: call await Task.
In your case, you'll have to change your thread class into a procedure that contains the code in your thread class. This procedure may be in any class. It must be declared async and return Task instead of void:
Of course you'll have to change your thread class into an async procedure:
private async Task MyThreadProcedureAsync(string fileName)
{
// do something really slow with fileName and return void
}
protected async void Button1_Click(object sender, EventArgs e)
{
string fileName = this.BrowseForFile();
if (!String.IsNullOrEmpty(fileName))
{
var myTask = Task.Run( () => MyThreadProcedureAsync(fileName))
// if desired do other things.
// before returning make sure the task is ready:
await myTask;
// during this wait the UI keeps responsive
}
}
private string BrowseForFileName()
{
using (var dlg = new System.Windows.Forms.OpenFileDialog())
{
// if needed set some properties; show the dialog:
var dlgResult = dlg.ShowDialog(this);
if (dlgResult == System.Windows.Forms.DialogResult.OK)
{
return dlg.FileName;
}
else
{
return null;
}
}
}
I have a task that runs in the form_load event of a usercontrol in winforms:
private void ucDeviceInsert_Load(object sender, EventArgs e)
{
System.Threading.Tasks.Task getTBox = System.Threading.Tasks.Task.Run(async () =>
{
await AVeryLongRunningProccess();
});
pbImage.Image = Properties.Resources.Remove;
getTBox.Wait();
pbImage.Image = Properties.Resources.Insert;
btnNext.Visible = true;
tmrDeviceInsert.Enabled = true;
tmrDeviceInsert.Start();
}
private void tmrDeviceInsert_Tick(object sender, EventArgs e)
{
Next();
}
I change the image of the picture box to inform the user the progress of the long running process. That part works fine, however the button doesn't show, and the timer never starts. I've stepped through the code, and I can confirm that it is running without any problems, which makes this even more baffling. Any ideas what would be causing this issue?
Task.Run is for pushing CPU-intensive work off the UI thread. Since you're calling an asynchronous method, I suspect it's not CPU-intensive.
So, you can just use async and await:
private async void ucDeviceInsert_Load(object sender, EventArgs e)
{
pbImage.Image = Properties.Resources.Remove;
await AVeryLongRunningProccess();
pbImage.Image = Properties.Resources.Insert;
btnNext.Visible = true;
tmrDeviceInsert.Enabled = true;
tmrDeviceInsert.Start();
}
Note that at the await, the UI is shown and the user can interact with it (that's the point).
getTBox.Wait() is going to try to complete that task synchronously. Therefore, the rest of the code after it won't happen until after the task completes.
I'd think you don't want your task to run synchronously at all, but rather handle its completion asynchronously, something like this:
getTBox.ContinueWith(() => updateStatusInUI());
I have to get the result from a web service. This is what I used:
EDIT:
private void Button_Click(object sender, RoutedEventArgs e)
{
webService.WebServiceHuscSoapClient a = new webService.WebServiceHuscSoapClient();
a.InsertNewUserCompleted += a_InsertNewUserCompleted;
a.InsertNewUserAsync("name", "phonenumber", "address");
}
void a_InsertNewUserCompleted(object sender, webService.InsertNewUserCompletedEventArgs e)
{
MessageBox.Show(e.Result.ToString());
}
Is there any way that I could put all this function and even handler to a class and when I want to get data from my webservice I would do something like this:
string json = MyWebService.GetData();
First, your call of DownloadStringAsync suggests passing in username and password, but it doesn't work like that. Check the documentation.
To (not really :-) ) answer your question: a far better approach these days is to use the new 'async/await' functionality available in C# 5. See this link for a comprehensive overview.
Your example then becomes trivial (no need to hook up a separate event handler anymore)
private async void Button_Click(object sender, RoutedEventArgs e)
{
WebClient webclient = new WebClient();
// TODO set up credentials
string result = await webclient.DownloadStringTaskAsync("http://your-url-here");
textBlock1.Text = str;
}
You could then still extract this in a separate, reusable (async) method:
private async Task<string> GetDataAsync()
{
WebClient webClient = new WebClient();
// TODO set up credentials
string result = await webclient.DownloadStringTaskAsync("http://your-url-here");
return result;
}
If you want to stick with the event-based approach, you could wrap the functionality in a separate class with it's own event, but that wouldn't bring you much gain IMO.
I figured it out from this article: How to use async-await with WCF in VS 2010 for WP7?
More: Async CTP - How can I use async/await to call a wcf service?
I wrote this on another class:
public static Task<int> InsertNewUser(string name, string phonenumber,string address) //can make it an extension method if you want.
{
TaskCompletionSource<int> tcs = new TaskCompletionSource<int>();
service.InsertNewUserCompleted += (object sender, WebService.InsertNewUserCompletedEventArgs e) => //change parameter list to fit the event's delegate
{
if (e.Error != null) tcs.SetResult(-1);
else
tcs.SetResult((int)e.Result);
};
service.InsertNewUserAsync(name, phonenumber,address);
return tcs.Task;
}
then I could call it from my class:
int su = await WebServiceHelper.SignUp("blabla", "0123465","huehuehue");
I do some tests with the new asynchronous pattern of C# 5.0 (async/await) I have a problem with understanding how the asynchronous methods are called.
Considering this code :
private async Task<string> DownloadAsync()
{
progress.ProgressChanged += (s, e) =>
{
progressBar1.Value = e.value;
};
return await DownloadSomething(myurl, progress);
}
private async void CallDownloadAsync()
{
string text = await DownloadAsync();
progressBar1.Value = 0;
label1.Text = "Done!";
}
private void button4_Click(object sender, EventArgs e)
{
CallDownloadAsync();
}
So, this code works very well. When I clic the "button4" a downloading task begins and my ProgressBar is updated correctly.
But, I'd like to compact my code a little bit more by removing CallDownloadAsync() method like this :
private void button4_Click(object sender, EventArgs e)
{
new Action(async () =>
{
string result = await Task.Run<string>(() => DownloadAsync());
}).Invoke();
label1.Text = "Running...";
}
So here, I want to directly initiate an action which calls the DownloadAsync method but when I hit my Button4 I have a Cross-thread operation not valid on the progressBar. So I do not understand what is the main difference between the Action() and the call of my CallDownloadAsync() method.
You may find my async/await intro helpful. In particular, an async method does not run on a background thread; Task.Run is used to run something on a background thread, hence the difference in your code.
In general, you should avoid async void, unless you're writing an async event handler. Like this:
private async void button4_Click(object sender, EventArgs e)
{
label1.Text = "Running...";
string result = await DownloadAsync();
progressBar1.Value = 0;
label1.Text = "Done!";
}
The difference is that in former case you call CallDownloadAsync() from UI thread (context).
In the latter case, DownloadAsync() is called from the initiated Task which is generally executed in a different thread created by TPL (Task Parallel Library) out of UI thread or threads created from it.
In WPF, UI components can be accessed only by a dedicated UI thread or (its children) threads created from under it (i.e with the same UI context).