Check if task is already running before starting new
As suggested by Jon Skeet, the Task.IsCompleted
is the better option.
According to MSDN:
IsCompleted
will return true when the task is in one of the three
final states:RanToCompletion
,Faulted
, orCanceled
.
But it appears to return true in the TaskStatus.WaitingForActivation
state too.
check if task with specific method is already running
You should avoid async void
. On a side note, I explain on my blog that the way you're using StartNew
is dangerous (you should use Task.Run
instead).
Applying both of these guidelines to your example, the code will look like this:
public async Task OnValueChangeAsync()
{
var progress = new Progress<int>(i => ProgresBar.Value = i);
Image im = await Task.Run(() => MyStaticClass.MyStaticFunction(progress));
Picture = im;
}
public async void OnValueChange(object sender, EventArgs e)
{
await OnValueChangeAsync();
}
At this point, it becomes more clear how to detect whether a method is already running (since that method actually returns a Task
now). One implementation is as such:
private async Task OnValueChangeImplAsync()
{
var progress = new Progress<int>(i => ProgresBar.Value = i);
Image im = await Task.Run(() => MyStaticClass.MyStaticFunction(progress));
Picture = im;
_onValueChangeTask = null;
}
private Task _onValueChangeTask;
public Task OnValueChangeAsync()
{
if (_onValueChangeTask != null)
return _onValueChangeTask;
_onValueChangeTask = OnValueChangeImplAsync();
return _onValueChangeTask;
}
public async void OnValueChange(object sender, EventArgs e)
{
await OnValueChangeAsync();
}
How to check if celery task is already running before running it again with beat?
No, Celery Beat knows nothing about the running tasks.
One way to achieve what you are trying to do is to link the task to itself. async_apply() for an example has optional parameter link
and link_error
which can be used to provide a signature (it can be a single task too) to run if the task finishes successfully (link) or unsuccessfully (link_error).
What I use is the following - I schedule task to run frequently (say every 5 minutes), and I use a distributed lock to make sure I always have only one instance of the task running.
Finally a reminder - you can always implement your own scheduler, and use it in your beat configuration. I was thinking about doing this in the past for exactly the same thing you want, but decided that the solution I already have is good enough for me.
ESP-IDF How to ckeck if task is already running?
eTaskGetState can be used to check if a task is already running, but such a solution can be susceptible to races. For example your task is technically still "running" when it's in fact "finishing", i.e. setting task_done = true;
and preparing for exit.
A better solution could be to use a queue (or a semaphore) and have the task run continuously, waiting for the messages to arrive and processing them in a loop.
Using a semaphore, you can do xSemaphoreTake(sem, 5000 / portTICK_PERIOD_MS);
to wait for either a wake-up condition or a timeout of 5 seconds, whichever comes first.
== EDIT ==
if there is no events task should wait. Only if event happens it should run the job. It should run it immediately if there was no execution in past 5 seconds. If there was an execution it should wait until 5 seconds since last execution and only then run it
You can achieve that by carefully managing the semaphore's ticks to wait. Something like this (untested):
TickType_t nextDelay = portMAX_DELAY;
TickType_t lastWakeup = 0;
const TickType_t minDelay = 5000 / portTICK_PERIOD_MS;
for (;;) {
bool signalled = xSemaphoreTake(sem, nextDelay);
TickType_t now = (TickType_t)(esp_timer_get_time() / (portTICK_PERIOD_MS * 1000));
if (signalled) {
TickType_t ticksSinceLastWakeup = now - lastWakeup;
if (ticksSinceLastWakeup < minDelay) {
// wakeup too soon - schedule next wakeup and go back to sleep
nextDelay = minDelay - ticksSinceLastWakeup;
continue;
}
}
lastWakeup = now;
nextDelay = portMAX_DELAY;
// do work ...
}
How to check if Async Task is already running
I think you should check the concept of Application
in Android
.
http://developer.android.com/reference/android/app/Application.html
In fact there is no such thing as
different instance of the app
. The Application
is always the same for all your Activities/Services.
That means that you'd left the Activity
and opened it again, 2 cases are possible:
- The system already killed your application. In this case
AsyncTask
is dead already and it's safe to start a new one - The
Application
was still alive, soAsyncTask
possibly still running.
In 2nd case I will recommend to use some static variables, pointing to this AsyncTask
or it's state. If your app was still alive when 2nd time opened - all static references will be still valid, so you can successfully operate.
PS: By the way, in current approach be aware that your application can be terminated by the system at any time. So AsyncTask
can be interrupted in any moment. It it's not ok for you - please check IntentServices
- components, specially designed for background-operation purpose. http://developer.android.com/reference/android/app/IntentService.html
Good luck!
Await an already running task
First of all, it is OK to await
the same task multiple times and it not gonna hurt your database. So, at least, you could cache such task (you're locking anyways, so it's safe) and later reuse it. That lets you to minimize locking time btw.
Secondly, since your resources are global by definition, it seems reasonable to precompute long-running query. Which means you run appropriate task right in the constructor (without await
ing it) and no locking is needed, not at all.
public MyConstructor()
{
_myCachedTask = LongRunningTask(); // don't await it; hopefully, task is now running somewhere on the thread pool
}
...
public Task LongRunningTask() => _myCachedTask; // it's OK to await it multiple times, thread safe as well
Does or does Task.Wait not start the task if it isn't already running?
Task
s are generally split into two groups - "cold" tasks and "hot" tasks. "cold" tasks are tasks that have not yet been started and are not meant to run yet. "hot" tasks are tasks that may or may not be currently running but, importantly, if they're not running yet, they may do so at any time. They're meant to be running but haven't yet been assigned the resource (a thread) they need to do so.
What this post is talking about is executing a "hot" task that hasn't otherwise had an opportunity to run. "hot" tasks are created by calling e.g. Task.Run()
. They're also e.g. the type of Task
s you'll receive from async methods. new Task(...)
, on the other hand gives you "cold" tasks. Unless or until you call Start
or moral equivalent methods on that task, it remains "cold". It's calling one of those methods explicitly that makes it "hot" instead of "cold".
Generally, you don't want to be working with "cold" tasks at all these days, which is why directly calling a Task
constructor is frowned upon. They were really a bad experiment from before they worked out how scheduling should really work. Most modern code doesn't expect to be working with "cold" tasks at all.
The key quote from the above post is this one:
However, if it hasn’t started executing, Wait may be able to pull the target task out of the scheduler to which it was queued and execute it inline on the current thread.
If you've not called Start
on the task, it hasn't been queued with a scheduler - so obviously we cannot do what the above says.
Check Task.Run Is Not Already Running
The Task.Run()
method returns a Task
object. You can, instead of immediate using await
with it, assign the Task
object reference to a variable, which you can then use later to check its status.
For example:
private Task _task;
private async void Window_PreviewKeyDown(object sender, KeyEventArgs e){
//check goes here - abort if running
if (_task != null && !_task.IsCompleted)
{
// Your code here -- use whatever mechanism you deem appropriate
// to interrupt the Calculate() method, e.g. call Cancel() on
// a CancellationToken you passed to the method, set a flag,
// whatever.
}
Task task = Task.Run(() => myMath.Calculate());
_task = task;
await _task;
if (task == _task)
{
// Only reset _task value if it's the one we created in this
// method call
_task = null;
}
}
Note that the above is a bit awkward. It's possible that there is a better mechanism for dealing with an already-running task in your scenario. But given the broadly stated requirement, I think the above is a reasonable approach.
Related Topics
C# Lamba With Datetime and Between
How to Set the Content-Type Header for an Httpclient Request
Web-Api Post Body Object Always Null
How to Generate Database Tables from C# Classes
Epplus: Find If the Entire Row Is Empty in Excel
Using C# Lambda to Split String and Search Value
Repaired Records:Cell Information from Worksheet Created from Scratch
How to Change a Image on a Button Using Windows Forms
How to Cast Object to List<Object> and Turn It into an Array
Entity Framework Core With Multiple Foreign Key on Same Column
Check If Task Is Already Running Before Starting New
How to Directly Print a Report Without Going Through Crystal Reports Viewer
How to Delete All Files in an Azure File Storage Folder
How Avoid Adding Duplicates to Database Managed by Entityframework Caused by Seed Method
Instantiating an Iformfile from a Physical File
C# Find Highest Array Value and Index