here is sample of code for
private void MethodStarter()
{
Task myFirstTask = Task.Factory.StartNew(Method1);
Task mySecondTask = Task.Factory.StartNew(Method1);
}
private void Method1()
{
// your code
}
private void Method2()
{
// your code
}
i am looking for code snippet for Parallel Tasks by which i can do the callback and pass argument to function also. can anyone help.
If I understood your question right this might be the anwser:
private void MethodStarter()
{
Task myFirstTask = Task.Factory.StartNew(() => Method1(5));
Task mySecondTask = Task.Factory.StartNew(() => Method2("Hello"));
}
private void Method1(int someNumber)
{
// your code
}
private void Method2(string someString)
{
// your code
}
If you want to start all the threads at the same time you can use the example given by h1ghfive.
UPDATE:
An example with callback that should work but I haven't tested it.
private void MethodStarter()
{
Action<int> callback = (value) => Console.WriteLine(value);
Task myFirstTask = Task.Factory.StartNew(() => Method1(5, callback));
Task mySecondTask = Task.Factory.StartNew(() => Method2("Hello"));
}
private void Method1(int someNumber, Action<int> intCallback)
{
// your code
intCallback(100); // will call the call back function with the value of 100
}
private void Method2(string someString)
{
// your code
}
You can alos look at Continuation if you don't want to pass in callback functions.
You should try something like this instead :
Parrallel.Invoke(
() => Method1(yourString1),
() => Method2(youString2));
Related
I have a WPF app running on .net 6 and an external device connected to it.
Initializing the device sometimes fails and I don't want to hold the UI thread trying to initialize it.
I want to run the following method (_device.Init()) in an async fashion and when it returns true, run Start() method.
edit: run it until it returns true from the _device.Init() method, not true for finishing the task
Is there a built-in functionality to do it with tasks? or any other "best practice" way?
Thank you :)
SomeDevice _device = new();
public async void Init()
{
// some other code
while (Task.Run(() => _device.Init()).Result == false)
{
}
Start();
}
public void Start()
{
// some other code
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
_device.Start();
}));
}
Instead of getting the Result of the Task (which may block the UI thread) you should await the Task:
public async void Init()
{
// some other code
while (!await Task.Run(() => _device.Init()))
{
}
Start();
}
The method should also be awaitable and be awaited when called, e.g. in an async Loaded event handler:
public async Task Init()
{
// some other code
while (!await Task.Run(() => _device.Init()))
{
}
Start();
}
...
await Init();
public async void Init()
{
var task = _device.Init();
//do work here
await task;
Start();
}
Should do the trick, it'll do the work and then wait for the task to complete before going to Start();
If you want to simply wait for init to finish and then run start it's even simpler with
await _device.Init().ContinueWith((x) => { Start();})
Hello How make method MethodA start new execution only when finished previous execution?
public class Program
{
public static void Main()
{
Console.WriteLine("Hello World");
MethodB();
MethodC();
}
public static void MethodA ()
{
Console.WriteLine("Start");
Thread.Sleep(200);
Console.WriteLine("Stop");
}
public static void MethodB()
{
Task.Run(() => MethodA());
}
public static void MethodC()
{
Task.Run(() => MethodA());
}
}
In this case I have this result
Hello World
Start
Start
Stop
Stop
But I need something like this
Hello World
Start
Stop
Start
Stop
The simplest way is to create a static locking object and reference that in MethodA:
private static readonly object _methodALockObject = new object();
public static void MethodA()
{
lock(_methodALockObject)
{
Console.WriteLine("Start");
Thread.Sleep(200);
Console.WriteLine("Stop");
}
}
Try to use async and await:
public static void Main()
{
Task.Run(async () =>
{
await MethodB();
await MethodC();
}).GetAwaiter().GetResult();
}
public static void MethodA()
{
Console.WriteLine("Start");
Thread.Sleep(200);
Console.WriteLine("Stop");
}
public async static Task MethodB()
{
await Task.Run(() => MethodA());
}
public async static Task MethodC()
{
await Task.Run(() => MethodA());
}
async and await keywords help to make your asynchronous code to be executed in syncronous order.
I have a snippet that looks like this,
private void btn_Click(object sender, EventArgs e)
{
try
{
var res = Task.Run(() => DoTask(param1, param2));
if(res.IsCompleted)
{
MessageBox.Show("Done");
}
MessageBox.Show("DoTask isn't called yet.");
}
catch
{
MessageBox.Show("Something wrong");
}
}
The DoTask method looks like this
private async Task<bool> DoTask(int p1, int p2)
{
// run long tasks
}
I'd want to show Done message after the task is done. But this never works. Instead the message DoTask isn't called yet. is always called before DoTask does tasks.
Panagiotis' answer is the way to go. Should you have the same situation in a method that is not an event handler and you can't use async for some reason, here's the next best option:
Task<bool> task = Task.Run(() => DoTask(param1, param2));
bool res = task.GetAwaiter().GetResult();
To get Result from Task.Run without await
The proper way to get a result from an asynchronous task is to use await:
private async void btn_Click(object sender, EventArgs e)
{
try
{
var res = await Task.Run(() => DoTask(param1, param2));
if(res)
{
MessageBox.Show("Done");
}
MessageBox.Show("DoTask isn't called yet.");
}
catch
{
MessageBox.Show("Something wrong");
}
}
Note that you should usually avoid async void, but since this code is an event handler, the async void is OK.
Simple Way:
bool result = DoTask(paran1, param2).Result;
No need to use Task.Run(). But you can use it in the following way (BAD WAY):
bool result = Task.Run(() => DoTask(paran1, param2).Result).Result;
I have initiated some async infinite loops in my WinForm application, but each time I am trying to break out of them, the program hangs up. I have read some similar topics where people suggested using CancellationTokens, but I am not able to adapt them to my needs. Here is the relevant part of my code.
static bool processStop = false;
static bool processStopped = false;
//Called once
private async void ProcessData()
{
while (!processStop)
{
await Task.Run
(
() =>
{
//Do stuff and call regular not async methods
}
);
}
processStopped = true;
}
//Button click handler to exit WinForm
btnExit.Click += (senders, args) =>
{
processStop = true;
//Programm hangs up here
while (!processStopped);
FormMain.Close();
}
Edited the code
The variables are static.
The Close method is the default Close() method for Forms.
The problem is that the call to Task.Run continues on the main thread. processStop = true; and while (!processStopped); execute synchronously one after the other. This doesn't let the ProcessData method continue its execution and a deadlock occures.
I see a couple of solutions:
Use ConfigureAwait(false) with Task.Run:
private async void ProcessData()
{
while (!processStop)
{
await Task.Run
(
() =>
{
//Do stuff and call regular not async methods
}
).ConfigureAwait(false);
}
processStopped = true;
}
This will cause the ProcessData to continue on a thread pool and you already use a thread pool by calling Task.Run, so it is not a great solution
Wrap the whole process in Task.Run:
static volatile bool processStop = false;
static volatile bool processStopped = false;
//Called once
private async void ProcessData()
{
await Task.Run(() =>
{
while (!processStop)
{
...
}
processStopped = true;
});
}
This would require changing the form of the method passed to work with the loop in it.
Make ProcessData a synchronous method to process CPU-intensive tasks and call it properly. CancellationToken would be the preferred way to cancel the task:
private void ProcessData(CancellationToken token)
{
while(!token.IsCancellationRequested)
{
// do work
}
}
And call it with this:
Task processingTask;
CancellationTokenSource cts;
void StartProcessing()
{
cts = new CancellationTokenSource();
processingTask = Task.Run(() => ProcessData(cts.Token), cts.Token);
}
btnExit.Click += async (senders, args) =>
{
cts.Cancel();
try
{
await processingTask;
}
finally
{
FormMain.Close();
}
}
If you want to spin a bunch of tasks without blocking you can do this:
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//Called once
private async Task ProcessData()
{
int count = 0;
while (true)
{
await Task.Run
(
() =>
{
this.Invoke(new Action(() => {
label2.Text = (count++).ToString();
label1.Text = DateTime.Now.ToString(); }));
Thread.Sleep(100);
}
);
}
Debugger.Break(); //you will never see this hit at all
}
private void button1_Click(object sender, EventArgs e)
{
this.Close();
}
private async void button2_Click(object sender, EventArgs e)
{
await ProcessData();
}
}
}
Say I have the following class definitions:
public class Calculator
{
public CalculatorResult Calculate()
{
return LongRunningCalculation();
}
private CalculatorResult LongRunningCalculation()
{
return new CalculatorResult(0.00);
}
}
public class ClassThatUsesACalculator
{
private readonly Calculator calculator;
public ClassThatUsesACalculator()
{
this.calculator = new Calculator();
}
public void DoWork()
{
for (int i = 0; i < 10; i++)
{
var result = calculator.Calculate();
DoSomethingWithCalculationResult(result);
DoLightWork();
OnProgressChanged();
}
}
}
public partial class Form : Form
{
public Form()
{
InitializeComponent();
}
private void Method(object sender, EventArgs e)
{
DoWork();
}
private void DoWork()
{
var calculator = new ClassThatUsesACalculator();
calculator.ProgressChanged += (s, e) =>
{
// Update progressbar
};
calculator.DoWork();
}
}
If I would want to do the work done in DoWork(), on the form, asynchronously I could add a method (GetCalculationTask) that returns a task using Task.Run() and add a async eventhandler i.e. For a button (MethodOne).
Please correct me if I'm wrong, but it seems to me that this would be the only option when the ClassThatUsesACalculator and Calculator classes reside in a library I don't own.
private Task GetCalculationTask(IProgress<CalculatorProgress> progress)
{
var calculator = new ClassThatUsesACalculator();
calculator.ProgressChanged += (s, e) =>
{
progress.Report(new CalculatorProgress(0));
};
return Task.Run(() =>
{
calculator.DoWork();
});
}
private async void MethodOne(object sender, EventArgs e)
{
IProgress<CalculatorProgress> progress = new Progress<CalculatorProgress> (UpdateProgressBar);
await GetCalculationTask(progress);
}
In the case I do own the library I think there are two more options, one of which very much like the first one. Probably due to the lack of my own understanding.
Create a method on on ClassThatUsesACalculator that encapsulates the DoWork() method and then call that from an asynchronous method on the form.
or,
Encapsulate the LongRunningCalculation() on the Calculator class with a Task.Run().
public Task<CalculatorResult> CalculateAsync()
{
return Task.Run(() =>
{
return LongRunningCalculation();
});
}
Create an async method on ClassThatUsesACalculator the calls that awaits the newly created method.
public async Task DoWorkAsync()
{
for (int i = 0; i < 10; i++)
{
var result = await calculator.CalculateAsync();
DoSomethingWithCalculationResult(result);
DoLightWork();
OnProgressChanged();
}
}
Create an asynchronous method on the form (MethodThree)
private async void MethodThree(object sender, EventArgs e)
{
IProgress<CalculatorProgress> progress = new Progress<CalculatorProgress>(UpdateProgressBar);
var calculator = new ClassThatUsesACalculator();
calculator.ProgressChanged += (s, args) =>
{
progress.Report(new CalculatorProgress(0));
};
await calculator.DoWorkAsync();
}
Now, in my opinion the last option would be the best as I would remain more control. But maybe I'm way off and would like someone's opinion or pointers on this as I can only find explanations on how to consume async, but never really how to build methods for others to consume.
As a general rule, push any Task.Run usage as far up the call stack as possible.
What you want to avoid is having a method with an asynchronous signature that is implemented using Task.Run in a reusable component. That's a lying API. I have a blog post on the subject that goes into greater detail.
If you control the classes in question, I recommend using IProgress<T> instead of events for progress updates. IProgress<T> works just fine with synchronous code as well as asynchronous:
public void DoWork(IProgress<CalculatorProgress> progress = null)
{
for (int i = 0; i < 10; i++)
{
var result = calculator.Calculate();
DoSomethingWithCalculationResult(result);
DoLightWork();
if (progress != null)
progress.Report(new CalculatorProgress(...));
}
}
Then using it is quite straightforward:
private async void MethodTwo(object sender, EventArgs e)
{
IProgress<CalculatorProgress> progress = new Progress<CalculatorProgress>(UpdateProgressBar);
var calculator = new ClassThatUsesACalculator();
await Task.Run(() => calculator.DoWork(progress));
}
That keeps the Task.Run usage in the component that needs it - the UI layer - and out of the business logic.