Windows form application timertick problem - c#

I used hold and release timer tick with modbus protocol.So It reads every second
Timer Interval : 1000
Enabled : True
I'm having a freezing problem. How can I fix it?
Please Help Me.
private void Timer1_Tick(object sender, EventArgs e)
{
ModBus1.Send_Device(Read, temperatureStartAddress, (ushort)TemperatureValueQnty, temperatureValue);
Thread.Sleep(250);
ModBus1.Send_Device(Read, temperatureStartAddress, (ushort)TemperatureValueQnty, temperatureValue);
Thread.Sleep(50);
if (SettingsTab.Enabled == true)
{
moduleTextBox.Text = temperatureValue[0].ToString();
moduleTextBox2.Text = temperatureValue[1].ToString();
moduleTextBox3.Text = temperatureValue[2].ToString();
moduleTextBox4.Text = temperatureValue[3].ToString();
moduleTextBox5.Text = temperatureValue[4].ToString();
moduleTextBox6.Text = temperatureValue[5].ToString();
moduleTextBox7.Text = temperatureValue[6].ToString();
moduleTextBox8.Text = temperatureValue[7].ToString();
moduleTextBox9.Text = temperatureValue[8].ToString();
moduleTextBox10.Text = temperatureValue[9].ToString();
moduleTextBox11.Text = temperatureValue[10].ToString();
moduleTextBox12.Text = temperatureValue[11].ToString();
}
}

After reading the comments, the real question is:
Method ModBus1.Send has a parameter temperatureValue which is an int[]. I want to convert the filled data to a List<double>
I wonder how you know how long you should make your array of integers, but let's assume you do know the length:
int temperatureValueCount = ...; // expected number of temperature values
int[] temperatureValues = new int[temperatureValueCount];
ModBus1.Send_Device(Read, temperatureStartAddress,
(ushort)TemperatureValueQnty,
temperatureValues);
// temperatureValues is now filled with integers
// convert this to a List<double> using LINQ:
List<double> returnValue = temperatureValues.Cast<double>().ToList();
Or if you don't like LINQ:
List<double> returnValue = new List<double>(temperatureValues.Length);
foreach (int temperatureValue in temperatureValues)
returnValue.Add((double)temperatureValue);
Back to the original question
I'm having a freezing problem.
If you use your user interface thread to do some lengthy processing, then during this processing your user interface is not responsive.
Nowadays there are two often used methods to prevent this:
Start a different thread to do this lengthy calculation
If your calculation is mostly waiting idly for another process, like waiting for a file to be written, a database query to be executed, or waiting for information of the internet, or in your case: waiting until some time has passed: use async-await.
async await is only useful if your thread will be waiting idly for something else.
If your thread has to do some heavy calculations, so if it will be really busy, consider to start a different thread to do the calculations. This way your user interface thread will be free to handle operator requests.
If you are not familiar with async-await, this interview with Eric Lippert really helped me to understand async-await. Search somewhere in the middle for async await.
Eric Lippert compares async await with a cook who has to make breakfast. He could start boiling water for the tea, wait until the water boils and make the tea. Then he puts bread in the toaster and wait idly until the bread is toasted. After that he boils some eggs, and waits idly until the eggs are finished.
You see all the idly waits for other processes. It would be much more efficient to put on the kettle for the tea, start toasting the bread and boiling the eggs. The task that finishes first continues first.
Async-await is similar: instead of waiting until the file has been written, or the database query returns data, your thread looks around to see if he can do something else, like responding to user input.
To use async await you'll have to change your code slightly.
Every method that uses async-await, must be declared async
Every async method should return Task<TResult> instead of TResult and Task instead of void
Only exception: event handlers (like button clicked), they return void.
Inside your async method, call other async methods and await for them to finish. In fact, your compiler will warn you if you forget to await.
If you don't need the results of the await immediately, don't await yet, continue processing until you need the result of the async method.
Make sure that every task has been awaited before you return from the async method, even if you don't need the result. If you don't await, you don't know when the task is finished, and thus will never know if you can safely destruct your class.
Just a convention: async method names have Async postfix. So you can keep them next to the non-async version: TextWriter.Write and TextWriter.WriteAsync.
.
async Task<int> CalculateOrderTotalAsync(int orderId)
{
Task<int> taskFetchOrderTotal = dbContext.OrderLines
.Where(orderLine => orderLine.OrderId == orderId)
.Select(orderLine => orderLine.Price)
.SumAsync();
// because you didn't await, you are free to do some other processing:
DoSomethingElse();
// now you need the result of the database query:
int orderTotal = await taskFetchOrderTotal();
return orderTotal;
}
While the database management system is executing the query, your thread is free to do something else. When it needs the results, it starts awaiting. If the database query is finished, it continues. If not, the thread doesn't wait idly, but goes up the call stack to execute other statements, until it sees an await, goes up the call stack again, etc.
Quite often, your task has noting else to do. In that case you'll see the await immediately before the call:
async Task SaveTextAsync(string fileName, string text)
{
using (var textWriter = File.CreateText(fileName))
{
await textWriter.WriteLineAsync(text);
}
}
Back to your question
Your thread is mostly waiting idly, in your Sleep methods. There is an async method to await some time: Task.Delay. If you use that in an async method your UI will be responsive.
private async Task<List<double> ReadTemperatureValuesAsync()
{
List<double> temperaturValues = new List<double>();
// tell the modbus to start reading the temperatures:
ModBus1.Send_Device(Read, temperatureStartAddress, (ushort)TemperatureValueQnty, temperatureValues);
// await 250 msec. The UI will be responsive
await Task.Delay(TimeSpan.FromSeconds(0.250));
// communicate with the modbus again. and await again:
ModBus1.Send_Device(Read, temperatureStartAddress, (ushort)TemperatureValueQnty, temperatureValues);
await Task.Delay(TimeSpan.FromMiliSeconds(50);
return temperatureValues;
}
You need a method to Display the Temperature values. This procedure has no idly wait. So no await needed:
private void DisplayMeasuredTemperatures(List<double> measuredTemperatures)
{
moduleTextBox.Text = temperatureValue[0].ToString();
moduleTextBox2.Text = temperatureValue[1].ToString();
...
}
Put it all together: async Measure and display the results:
private async Task MeasureAndDisplayTemperaturesAsync()
{
List<double> measuredTemperatures = await this.ReadTemperatureValuesAsync();
if (SettingsTab.Enabled)
{
DisplayMeasuredTemperatures(measuredTemperatures);
}
}
Finally your timer tick method. This is an event handler: return void instead of Task:
private async void Timer1_Tick(object sender, EventArgs e)
{
await MeasureAndDisplayTemperaturesAsync();
}
If you want to call it after a button click:
private async void Button1_Click(object sender, EventArgs e)
{
await MeasureAndDisplayTemperaturesAsync();
}
Long calculations
If your method doesn't have to wait for another process, but has some long calculations to do, think of starting a Task, and await for it to finish.
private int SomeLongCalculations(Customer customer)
{
int result = 0;
for (long i=0; i<10000000000000000000000; ++i)
{
... // something with Customer and i
}
return result;
}
private async Task<int> CalculateAsync(Customer customer)
{
int calculationResult = await Task.Run(() => this.SomeLongCalculations(customer);
return calculationResult;
}

Related

Combining CPU-bound and IO-bound work in async method

There is such application:
static void Main(string[] args)
{
HandleRequests(10).Wait();
HandleRequests(50).Wait();
HandleRequests(100).Wait();
HandleRequests(1000).Wait();
Console.ReadKey();
}
private static async Task IoBoundWork()
{
await Task.Delay(100);
}
private static void CpuBoundWork()
{
Thread.Sleep(100);
}
private static async Task HandleRequest()
{
CpuBoundWork();
await IoBoundWork();
}
private static async Task HandleRequests(int numberOfRequests)
{
var sw = Stopwatch.StartNew();
var tasks = new List<Task>();
for (int i = 0; i < numberOfRequests; i++)
{
tasks.Add(HandleRequest());
}
await Task.WhenAll(tasks.ToArray());
sw.Stop();
Console.WriteLine(sw.Elapsed);
}
Below the output of this app:
From my perspective having CPU-bound and IO-bound parts in one method it is quite regular situation, e.g. parsing/archiving/serialization of some object and saving that to the disk, so it should probably work well. However in the implementation above it works very slow. Could you please help me to understand why?
If we wrap the body of CpuBoundWork() in Task it significantly improve performance:
private static async Task CpuBoundWork()
{
await Task.Run(() => Thread.Sleep(100));
}
private static async Task HandleRequest()
{
await CpuBoundWork();
await IoBoundWork();
}
Why it works so slow without Task.Run? Why we can see performance boost after adding Task.Run? Should we always use such approach in similar methods?
for (int i = 0; i < numberOfRequests; i++)
{
tasks.Add(HandleRequest());
}
The returned task is created at the first await in the HandleRequest(). So you are executing all CPU bound code on one thread: the for loop thread. complete serialization, no parallelism at all.
When you wrap the CPU part in a task you are actually submitting the CPU part as Tasks, so they are executed in parallel.
The way you're doing, this is what happens:
|-----------HandleRequest Timeline-----------|
|CpuBoundWork Timeline| |IoBoundWork Timeline|
Try doing it like this:
private static async Task HandleRequest()
{
await IoBoundWork();
CpuBoundWork();
}
It has the advantage of starting the IO work and while it waits, the CpuBoundWork() can do the processing. You only await at the last moment you need the response.
The timeline would look somewhat like this:
|--HandleRequest Timeline--|
|Io...
|CpuBoundWork Timeline|
...BoundWork Timeline|
On a side note, open extra threads (Task.Run) with caution in an web environment, you already have a thread per request, so multiplying them will have a negative impact on scalability.
You've indicated that your method ought to be asynchronous, by having it return a Task, but you've not actually made it (entirely) asynchronous. You're implementation of the method does a bunch of expensive, long running, work synchronously, and then returns to the caller and does some other work asynchronously.
Your callers of the method, however, assume that it's actually asynchronous (in entirety) and that it doesn't do expensive work synchronously. They assume that they can call the method multiple times, have it return immediately, and then continue on, but since your implementation doesn't return immediately, and instead does a bunch of expensive work before returning, that code doesn't work properly (specifically, it's not able to start the next operation until the previous one returns, so that synchronous work isn't being done in parallel).
Note that your "fix" isn't quite idiomatic. You're using the async over sync anti-pattern. Rather than making CpuBoundWork async and having it return a Task, despite being a CPU bound operation, it should remain as is an HandleRequest should handle indicating that the CPU bound work should be done asynchronously in another thread by calling Task.Run:
private static async Task HandleRequest()
{
await Task.Run(() => CpuBoundWork());
await IoBoundWork();
}

I cannot understand how exactly does await/async work

I started to look into Task, async/await concepts is c# and I'm having big problems understanding it, well at least i don't know how to implement it. I started rewriting an older test program i had written before, but now instead of threading i want to use these new concepts. Basically the layout is as it follows:
I have a simple class where i download the HTML content of a web page.
I process that in another class where i basically just parse the page to my model. Later on i want to display that to my UI.
The problem is that my program is not responsive, it blocks the UI while I'm processing the info.
I started learning this 2 days ago, i have read a lot of stuff online, including MSDN and some blogs but yet I'm unable to figure it out. Maybe someone can provide a look as well
HtmlDOwnloadCOde:
public async Task<string> GetMangaDescriptionPage(string detailUrl)
{
WebClient client = new WebClient();
Stream data = await client.OpenReadTaskAsync(detailUrl);
StreamReader reader = new StreamReader(data);
string s = reader.ReadToEnd();
data.Dispose();
reader.Dispose();
data.Close();
reader.Close();
return s;
}
My parse class code:
public async Task<MangaDetailsModel> ParseMangaDescriptionPage()
{
ParseOneManga pom = new ParseOneManga();
string t1 = await pom.GetMangaDescriptionPage(selectedManga.url);
HtmlDocument htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(t1);
var divs = htmlDoc.DocumentNode.Descendants("div").Where(x => x.Attributes.Contains("id") &&
x.Attributes["id"].Value.Contains("title")).ToArray();
mangaDetails.mangaName = divs[0].Element("h1").InnerText;
mangaDetails.description = divs[0].Descendants("p").Single().InnerText ?? "DSA";
var tds = divs[0].Descendants("td");
int info = 0;
var chapters = htmlDoc.DocumentNode.Descendants("div").Where(x => x.Attributes.Contains("id") &&
x.Attributes["id"].Value.Contains("chapters")).ToArray();
var chapterUi = chapters[0].Descendants("ul").Where(x => x.Attributes.Contains("class") &&
x.Attributes["class"].Value.Contains("chlist"));
foreach (var li in chapterUi)
{
var liChapter = li.Descendants("li");
foreach (var h3tag in liChapter)
{
var chapterH3 = h3tag.Descendants("a").ToArray();
SingleManagFox chapterData = new SingleManagFox();
chapterData.name = chapterH3[1].InnerHtml;
chapterData.url = chapterH3[1].GetAttributeValue("href", "0");
mangaDetails.chapters.Add(chapterData);
}
};
return mangaDetails;
}
UI code:
private async void mainBtn_Click(object sender, RoutedEventArgs e)
{
if (mangaList.SelectedItem != null)
{
test12((SingleManagFox)mangaList.SelectedItem);
}
}
private async void test12(SingleManagFox selectedManga)
{
selectedManga = (SingleManagFox)mangaList.SelectedItem;
MangaDetails mangaDetails = new MangaDetails(selectedManga);
MangaDetailsModel mdm = await mangaDetails.ParseMangaDescriptionPage();
txtMangaArtist.Text = mdm.artisName;
txtMangaAuthor.Text = mdm.authorName;
chapterList.ItemsSource = mdm.chapters;
}
Sorry if its trivial but i cannot figure it out myself.
When going async you need to try to go async all the way and avoid mixing blocking calls with async calls.
You are using async void in the event handler with no await.
Try to avoid async void unless it is an event handler. test12 should be updated to return Task and awaited in the event handler mainBtn_Click.
private async void mainBtn_Click(object sender, RoutedEventArgs e) {
if (mangaList.SelectedItem != null) {
await test12((SingleManagFox)mangaList.SelectedItem);
}
}
private async Task test12(SingleManagFox selectedManga) {
selectedManga = (SingleManagFox)mangaList.SelectedItem;
MangaDetails mangaDetails = new MangaDetails(selectedManga);
MangaDetailsModel mdm = await mangaDetails.ParseMangaDescriptionPage();
txtMangaArtist.Text = mdm.artisName;
txtMangaAuthor.Text = mdm.authorName;
chapterList.ItemsSource = mdm.chapters;
}
Also consider updating the web call to use HttpClient if available.
class ParseOneManga {
public async Task<string> GetMangaDescriptionPageAsync(string detailUrl) {
using (var client = new HttpClient()) {
string s = await client.GetStringAsync(detailUrl);
return s;
}
}
}
Reference: - Async/Await - Best Practices in Asynchronous Programming
Quite often people think that async-await means that multiple threads are processing your code at the same time. This is not the case, unless you explicitly start a different thread.
A good metaphore that helped me a lot explaining async-await is the restauran metaphor used in this interview with Eric Lippert. Search somewhere in the middle for async-await.
Eric Lipperts compares async-await processing with a cook who has to wait for his water to boil. Instead of waiting, he looks around if he can do other things instead. When finished doing the other thing, he comes back to see if the water is boiling and starts processing the boiling water.
The same is with your process. There is only one thread busy (at a time). This thread keeps processing until he has to await for something. This something is usually a fairly long process that is processed without using your CPU core, like writing a file to disk, loading a web page, or querying information from an external database.
Your thread can only do one thing at a time. So while it is busy calculating something, if can't react on operator input and your UI freezes, until the calculations are done. Async await will only help if there are a lot of times your thread would be waiting for other processes to complete
If you call an async function, you are certain that somewhere in that function is an await. In fact, if you declare your function async, and your forget to await in it, your compiler will warn you.
When your call meets the await in the function, your thread goes up its call stack to see if it can do other things. If you are not awaiting, you can continue processing, until you have to await. The thread goes up its call stack again to see if one of the callers is not awaiting etc.
async Task ReadDataAsync()
{
// do some preparations
using (TextReader textReader = ...)
{
var myReadTask = textReader.ReadToEndAsync();
// while the textReader is waiting for the information to be available
// you can do other things
ProcessSomething();
// after a while you really need the results from the read data,
// so you await for it.
string text = await MyReadTask;
// after the await, the results from ReatToEnd are available
Process(text);
...
There are some rules to follow:
an async function should return Task instead of void and Task<TResult> instead of TResult
There is one exception: the async event handler returns void instead of Task.
Inside your async function you should await somehow. If you don't await, it is useless to declare your function async
The result of await Task is void, and the result of await Task<TResult> is TResult
If you call an async function, see if you can do some processing instead of waiting for the results of the call
Note that even if you call several async functions before awaiting for them, does not mean that several threads are running these functions synchronously. The statement after your first call to the async function is processed after the called function starts awaiting.
async Task DoSomethingAsync()
{
var task1 = ReadAsync(...);
// no await, so next statement processes as soon as ReadAsync starts awaiting
DoSomeThingElse();
var task2 = QueryAsync(...);
// again no await
// now I need results from bothtask1, or from task2:
await Task.WhenAll(new Task[] {task1, task2});
var result1 = Task1.Result;
var result2 = Task2.Result;
Process(result1, result2);
...
Usually all your async functionality is performed by the same context. In practice this means that you can program as if your program is single threaded. This makes the look of your program much easier.
Another article that helped me a lot understanding async-await is Async-Await best practices written by the ever so helpful Stephen Cleary

Executing multiple tasks asynchronously in C#

Environment
Windows 7
Visual Studio
C#
What I'm trying to do
I'm trying to build an app to evaluate company products. For security, the description below is made abstract to some extent.
What this app does is changing a certain parameter in the product and see how a certain value of the product changes. So I need to do two things.
Change the parameter at a certain interval
Display the value in a textbox at a certain interval
The diagram is like this.
These tasks should be repeated until a cancel button is pressed.
The UI has these controls:
button1 : start button
button2 : cancel button
textbox1 : to show values obtained from the device
So here is the code I wrote.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
CancellationTokenSource cts = new CancellationTokenSource();
private async void button1_Click(object sender, EventArgs e)
{
await Task1();
await Task2();
}
private async Task Task1()
{
while (!cts.IsCancellationRequested)
{
Thread.Sleep(500);
ChangeParameter(0);
Thread.Sleep(1000);
ChangeParameter(10);
Thread.Sleep(500);
ChangeParameter(0);
}
}
private void ChangeParameter(double param)
{
// change device paremeter
Console.WriteLine("devicep parameter changed : " + param);
}
private async Task Task2()
{
while (!cts.IsCancellationRequested)
{
Thread.Sleep(100);
int data = GetDataFromDevice();
UpdateTextBoxWithData(data);
}
cts.Token.ThrowIfCancellationRequested();
}
private int GetDataFromDevice()
{
//pseudo code
var rnd = new Random();
return rnd.Next(100);
}
private void UpdateTextBoxWithData(int data)
{
textBox1.AppendText(data.ToString() + "\n");
// debug
Console.WriteLine("data : " + data);
}
private void button2_Click(object sender, EventArgs e)
{
cts.Cancel();
}
}
Issues
However, there are two issues in this code.
UI freezes.
Task2 is never executed.
The second issue is derived from await since it executes tasks one by one. I could have used Task.Run() but this doesn't allow adding values to textBox since it's different from the UI thread.
How can I solve these issues? Any help would be appreciated.
First of all, async methods can be illusive as they won't turn your methods magically asynchronous. Instead, you can consider an async method as a setup for a state machine (see a detailed explanation here), where you schedule the chain of operations by the await calls.
For that reason, your async methods must execute as fast as possible. Do not do any blocking operation in such a setup method. If you have a blocking operation, which you want to execute in the async method, schedule it by an await Task.Run(() => MyLongOperation()); call.
So for example this will return immediately:
private async Task Task1()
{
await Task.Run(() =>
{
while (!cts.IsCancellationRequested)
{
Thread.Sleep(500);
ChangeParameter(0);
Thread.Sleep(1000);
ChangeParameter(10);
Thread.Sleep(500);
ChangeParameter(0);
}
}
}
A small remark: others may suggest to use Task.Delay instead of Thread.Sleep. I would say that use Task.Delay only if it is the part of the configuration of your state machine. But if the delay is intended to be used as a part of the long-lasting operation, which you don't want to split up, you can simply stay at the Thread.Sleep.
Finally, a remark for this part:
private async void button1_Click(object sender, EventArgs e)
{
await Task1();
await Task2();
}
This configures your tasks to be executed after each other. If you want to execute them parallel, do it like this:
private async void button1_Click(object sender, EventArgs e)
{
Task t1 = Task1();
Task t2 = Task2();
await Task.WhenAll(new[] { t1, t2 });
}
Edit: An extra note for long-lasting tasks: By default, Task.Run executes the tasks on pool threads. Scheduling too many parallel and long lasting tasks might cause starvation and the whole application may freeze for long seconds. So for long-lasting operation you might want to use Task.Factory.StartNew with TaskCreationOptions.LongRunning option instead of Task.Run.
// await Task.Run(() => LooongOperation(), token);
await Task.Factory.StartNew(() => LooongOperation(), token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
The problem is you not using await in your tasks so they executing synchronously.
You should use something like this to maintain your UI responsive (NOTE this is not production code, I'm just showing an idea):
private void button1_Click(object sender, EventArgs e)
{
try
{
await Task.WhenAll(Task1(cts.Token), Task2(cts.Token));
}
catch (TaskCancelledException ex)
{
}
}
private async Task Task1(CancellationToken token)
{
while (true)
{
token.ThrowIfCancellationRequested();
await Task.Delay(500, token); // pass token to ensure delay canceled exactly when cancel is pressed
ChangeParameter(0);
await Task.Delay(1000, token);
ChangeParameter(10);
await Task.Delay(500, token);
ChangeParameter(0);
}
}
private async Task Task2(CancellationToken token)
{
while (true)
{
token.ThrowIfCancellationRequested();
await Task.Delay(100, token);
int data = await Task.Run(() => GetDataFromDevice()); //assuming this could be long running operation it shouldn't be on ui thread
UpdateTextBoxWithData(data);
}
}
Basically, when you need to run something on background you should wrap that in Task.Run() and then await for result. Simply adding async to your method won't make this method asynchronous.
To make your code clearer, I suggest you to move methods like GetDataFromDevice or ChangeParameter to services layer. Also, take a look at IProgress as comments suggests to update your UI according to progress of some process.
There are many issues with this code:
async/await doesn't make the code asynchronous automagically. It allows you to await the results of already asynchronous operations. If you want to run something in the background that isn't already asynchronous, you need to use Task.Run or a similar method to start a Task.
await returns execution to the original synchronization context. In this case, the UI thread. By using Thread.Sleep, you are freezing the UI thread
You can't update the UI from another thread and that goes for Tasks too. You can use the IProgress interface though to report progress. A lot of BCL classes use this interface, just like CancellationToken
Maxim Kosov already cleaned up the code and shows how to properly use async/await and Task.Run, so I'll just post how to use IProgress< T> and its impelementation, Progress< T>
IProgress is used to publich a progress update with the IProgress< T>.Report method. Its default implementation, Progress, raises the ProgressChanged event and/or calls the Action<T> passed to its constructor, on the UI thread. Specifically, on the synchronization context captured when the class was created.
You can create a progress object in your constructor or your button click event, eg
private async void button1_Click(object sender, EventArgs e)
{
var progress=new Progress<int>(data=>UpdateTextBoxWithData(data));
//...
//Allow for cancellation of the task itself
var token=cts.Token;
await Task.Run(()=>MeasureInBackground(token,progress),token);
}
private async Task MeasureInBackground(CancellationToken token,IProgress<int> progress)
{
while (!token.IsCancellationRequested)
{
await Task.Delay(100,token);
int data = GetDataFromDevice();
progress.Report(data);
}
}
Note that using Thread.Sleep inside a task is not a good idea because it wastes a threadpool thread doing nothing. It's better to use await Task.Delay() which requires that the signature of the method change to async Task. There is a Task.Run(Func) overload just for this purpose.
The method is a bit different from Maxim Kosov's code to show that IProgress really communicates across threads. IProgress can handle complex classes, so you could return both a progress percentage and a message, eg:
private async Task MeasureInBackground(CancellationToken token,IProgress<Tuple<int,string>> progress)
{
while(!token.IsCancellationRequested)
{
await Task.Delay(100,token);
int data = GetDataFromDevice();
progress.Report(Tuple.Create(data,"Working"));
}
progress.Report(Tuple.Create(-1,"Cancelled!"));
}
Here I'm just being lazy and return a Tuple<int,string>. A specialized progress class would be more appropriate in production code.
The advantage of using an Action is that you don't need to manage event handlers and the objects are local to the async method. Cleanup is performed by .NET itself.
If your device API provides truly asynchronous calls, you don't need Task.Run. This means that you don't have to waste a Task in a tigh loop, eg:
private async Task MeasureInBackground(CancellationToken token,IProgress<Tuple<int,string>> progress)
{
while(!token.IsCancellationRequested)
{
await Task.Delay(100, token);
int data = await GetDataFromDeviceAsync();
progress.Report(Tuple.Create(data,"Working"));
}
progress.Report(Tuple.Create(-1,"Cancelled!"));
}
Most drivers perform IO tasks using an OS feature called completion ports, essentially callbacks that are called when the driver completes an operation. This way they don't need to block while waiting for a network, database or file system response.
EDIT
In the last example, Task.Run is no longer needed. Just using await would be enough:
await MeasureInBackground(token,progress);

What is best way to fake a long running process in parallel processing?

I was wondering what is the best way to fake a long running task when multiple tasks are being run in parallel. First thing that comes on mind is Thread.Sleep
public void FakeLongRunningTask()
{
Thread.Sleep(5000);
}
However problem with above code is that calling Thread.Sleep will block this thread which means it will give up it's processor time slice, so calling a method with Thread.Sleep in a parallel environment is as good as not calling it at all. So if I'm running three tasks in parallel and One of which is calling Thread.Sleep, then this task will have no effect on performance (though It might force CLR to generate more threads !!!). But what i want is to fake a task which would effect the overall performance.
If you want a busy wait which will keep one core of the processor occupied, you could try something like this:
public void BusyWait(int milliseconds)
{
var sw = Stopwatch.StartNew();
while (sw.ElapsedMilliseconds < milliseconds)
Thread.SpinWait(1000);
}
Using the 4.5 framework, I think you can use Task.Delay
EDIT: In response to a request. Here's an untested sample:
async Task LongRunningOperation()
{
await Task.Delay(5000);
}
private async void SomeEvent(object sender, EventArgs e)
{
await LongRunningOperation();
}
2nd EDIT: Using the 4.0 framework, this may work (untested):
Task Delay(int interval)
{
var z = new TaskCompletionSource<object>();
new Timer(_ => z.SetResult(null)).Change(interval, -1);
return z.Task;
}
You almost did it:
public async Task FakeLongRunningTask()
{
await Task.StartNew(() => Thread.Sleep(5000));
}
and usage in some event (sorry, Big Daddy =D):
private async void SomeEvent(object sender, EventArgs e)
{
await FakeLongRunningTask();
}
Notice, what you have to use it with await (which required caller method to be marked with async).

What's the new C# await feature do? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
Can anyone explain what the await function does?
They just talked about this at PDC yesterday!
Await is used in conjunction with Tasks (parallel programming) in .NET. It's a keyword being introduced in the next version of .NET. It more or less lets you "pause" the execution of a method to wait for the Task to complete execution. Here's a brief example:
//create and run a new task
Task<DataTable> dataTask = new Task<DataTable>(SomeCrazyDatabaseOperation);
//run some other code immediately after this task is started and running
ShowLoaderControl();
StartStoryboard();
//this will actually "pause" the code execution until the task completes. It doesn't lock the thread, but rather waits for the result, similar to an async callback
// please so also note, that the task needs to be started before it can be awaited. Otherwise it will never return
dataTask.Start();
DataTable table = await dataTask;
//Now we can perform operations on the Task result, as if we're executing code after the async operation completed
listBoxControl.DataContext = table;
StopStoryboard();
HideLoaderControl();
Basically, the async and await keywords allow you to specify that execution of a method should stop at all usages of await, which mark asynchronous method calls, and then resume once the asynchronous operation is complete. This allows you to call a method in an app's main thread and handle complex work asynchronously, without the need to explicitly define threads and joins or blocking the app's main thread.
Think of it as being somewhat similar to a yield return statement in a method producing an IEnumerable. When the runtime hits the yield, it will basically save the method's current state, and return the value or reference being yielded. The next time IEnumerator.MoveNext() is called on the return object (which is generated internally by the runtime), the method's old state is restored to the stack and execution continues with the next line after the yield return as if we'd never left the method. Without this keyword, an IEnumerator type must be custom-defined to store state and handle the iteration requests, with methods that can become VERY complex indeed.
Similarly, a method marked as async must have at least one await. On an await, the runtime will save the current thread's state and call stack, make the asynchronous call, and unwind back to the runtime's message loop to handle the next message and keep the app responsive. When the asynchronous operation is complete, at the next scheduling opportunity, the call stack to up the async operation is pushed back in and continued as if the call was synchronous.
So, these two new keywords basically simplify the coding of asynchronous processes, much like yield return simplified the generation of custom enumerables. With a couple keywords and a little background knowledge, you can skip all the confusing and often error-prone details of a traditional asynchronous pattern. This will be INVALUABLE in pretty much any event-driven GUI app like Winforms, WPF of Silverlight.
The currently accepted answer is misleading.
await is not pausing anything.
First of all it can be used only in methods or lambdas marked as async and returning Task or void if you don't care having Task instance running in this method.
Here is an illustration:
internal class Program
{
private static void Main(string[] args)
{
var task = DoWork();
Console.WriteLine("Task status: " + task.Status);
Console.WriteLine("Waiting for ENTER");
Console.ReadLine();
}
private static async Task DoWork()
{
Console.WriteLine("Entered DoWork(). Sleeping 3");
// imitating time consuming code
// in a real-world app this should be inside task,
// so method returns fast
Thread.Sleep(3000);
await Task.Run(() =>
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine("async task iteration " + i);
// imitating time consuming code
Thread.Sleep(1000);
}
});
Console.WriteLine("Exiting DoWork()");
}
}
Output:
Entered DoWork(). Sleeping 3
async task iteration 0
Task status: WaitingForActivation
Waiting for ENTER
async task iteration 1
async task iteration 2
async task iteration 3
async task iteration 4
async task iteration 5
async task iteration 6
async task iteration 7
async task iteration 8
async task iteration 9
Exiting DoWork()
For anyone new to asynchronous programming in .NET, here's a (totally fake) analogy in a scenario you may be more familiar with - AJAX calls using JavaScript/jQuery. A simple jQuery AJAX post looks like this:
$.post(url, values, function(data) {
// AJAX call completed, do something with returned data here
});
The reason we process the results in a callback function is so we don't block the current thread while waiting for the AJAX call to return. Only when the response is ready will the callback get fired, freeing the current thread to do other things in the mean time.
Now, if JavaScript supported the await keyword (which of course it doesn't (yet!)), you could achieve the same with this:
var data = await $.post(url, values);
// AJAX call completed, do something with returned data here
That's a lot cleaner, but it sure looks like we introduced synchronous, blocking code. But the (fake) JavaScript compiler would have taken everything after await and wired it into a callback, so at runtime the second example would behave just like the first.
It may not seem like it's saving you much work, but when it comes to things like exception handling and synchronization contexts, the compiler is actually doing a lot of heavy lifting for you. For more, I'd recommend the FAQs followed by Stephen Cleary's blog series.
If I had to implement it in Java it would look some thing like this:
/**
* #author Ilya Gazman
*/
public abstract class SynchronizedTask{
private ArrayList<Runnable> listeners = new ArrayList<Runnable>();
private static final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(6, 6, 0, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(1000));
public final void await(Runnable listener){
synchronized (this) {
listeners.add(listener);
}
}
public void excecute(){
onExcecute();
for (int i = listeners.size() - 1; i >= 0; i--) {
Runnable runnable;
synchronized (this) {
runnable = listeners.remove(i);
}
threadPoolExecutor.execute(runnable);
}
}
protected abstract void onExcecute();
}
Your application would use it like this:
public class Test{
private Job job = new Job();
public Test() {
craeteSomeJobToRunInBackground();
methode1();
methode2();
}
private void methode1(){
System.out.println("Running methode 1");
job.await(new Runnable() {
#Override
public void run() {
System.out.println("Continue to running methode 1");
}
});
}
private void methode2(){
System.out.println("Running methode 2");
}
private void craeteSomeJobToRunInBackground() {
new Thread(new Runnable() {
#Override
public void run() {
job.excecute();
}
}).start();
}
private class Job extends SynchronizedTask{
#Override
protected void onExcecute() {
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Job is done");
}
}
}

Categories

Resources