BackgroundTask deferral.Complete - c#

My question is, what does the deferral.complete() method exactly, does this method call the event task.Compledet, or is there a way to call a method from the BackgroundTaskSyncer in my class BackgroundSyncer ????
When i run the Programm i will do the Run method from BackgroundTaskSyncer but nothing in the other class??
namespace NotificationTask
{
public sealed class BackgroundTaskSyncer : IBackgroundTask
{
public void Run(IBackgroundTaskInstance taskInstance)
{
BackgroundTaskDeferral deferral = taskInstance.GetDeferral();
deferral.Complete();
}
}
}
namespace Services
{
public static class BackgroundSync
{
private static async Task RegisterBackgroundTask()
{
try
{
BackgroundAccessStatus status = await BackgroundExecutionManager.RequestAccessAsync();
if (status == BackgroundAccessStatus.AllowedWithAlwaysOnRealTimeConnectivity || status == BackgroundAccessStatus.AllowedMayUseActiveRealTimeConnectivity)
{
bool isRegistered = BackgroundTaskRegistration.AllTasks.Any(x => x.Value.Name == "Notification task");
if (!isRegistered)
{
BackgroundTaskBuilder builder = new BackgroundTaskBuilder
{
Name = "Notification task",
TaskEntryPoint =
"NotificationTask.BackgroundTaskSyncer"
};
builder.SetTrigger(new TimeTrigger(15, false));
builder.AddCondition(new SystemCondition(SystemConditionType.InternetAvailable));
BackgroundTaskRegistration task = builder.Register();
task.Completed += new BackgroundTaskCompletedEventHandler(OnCompleted);
task.Progress += new BackgroundTaskProgressEventHandler(OnProgress);
}
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("The access has already been granted");
}
}
private static void OnCompleted(IBackgroundTaskRegistration task, BackgroundTaskCompletedEventArgs args)
{
ToTheBackGroundWork();
}

Deferrals were created to work around a problem with async void events and methods. For example, if you had to await during a background operation, you would use an async void Run method. But the problem with that is that the runtime has no idea that you actually have more work you want to do.
So, a deferral is an object that you can use to inform the runtime "I'm really done now." A deferral is only necessary if you need to await.
I have a blog post that goes into "asynchronous event handlers" and deferrals in more detail.

Related

await Task.Delay(1000); causing crashes - Unity C#

Main Issue:
Unsure of what's happening in the background, but apparently whenever the line await Task.Delay(1000); is called Unity would turn unresponsive/freezes up.
Error msg:
Tried checking callbacks from unity's profiler, but whenever the line in question were triggered unity would instantly turn unresponsive and not allowing any interaction (no callbacks/error messages were given out either).
Goal:
The goal here is to simply call tryActivities[0] then, await for 1 second and then return true, and prints "Fished successfully!", without any crashing.
Suspicions:
A suspicion I have is that the line tryActivities.Add(new Func<bool>(() => fs(currentSlot.basicData.typeID).Result)); need some sort of await? Though I'm also unsure of how to implement that either.
Inventory inventory; (Inventory.cs)
List<Func<bool>> tryActivities = new List<Func<bool>>();
public delegate Task<bool> Fish(int ID); Fish fs;
void Start()
{
fs = new Fish(activities.Fish);
tryActivities.Add(new Func<bool>(() => fs(currentSlot.basicData.typeID).Result));//await? how?
}
public void Interact()//called when a button is pressed
{
if (TryPlaceOrUse()) print("Fished successfully!");
else print("Fishing failed");
}
bool TryPlaceOrUse()
{
if (tryActivities[(int)currentSlot.basicData.myActivity]())//tryActivities[0]
return true;
return false;
}
Activities activities; (Activities.cs)
public async Task<bool> Fish(int ID)
{
await Task.Delay(1000);//crashes here
return true;
}
This might do what you want. This is how you'd use a list of async Funcs, which is really just a list of Funcs that return Tasks of bool.
public class Program
{
public delegate Task<bool> Fish(int ID);
Fish fs;
List<Func<Task<bool>>> tryActivities = new List<Func<Task<bool>>>();
public async static Task Main()
{
Console.WriteLine("Hello, World!");
Program program = new Program();
program.Start();
await program.Interact();
}
void Start()
{
fs = new Fish(Activities.Fish);
tryActivities.Add(new Func<Task<bool>>(async () => await fs(4)));//await? how? like this :)
}
public async Task Interact() //called when a button is pressed
{
if (await TryPlaceOrUse())
Console.WriteLine("Fished successfully!");
else
Console.WriteLine("Fishing failed");
}
async Task<bool> TryPlaceOrUse()
{
if (await tryActivities[0]()) //tryActivities[0]
return true;
return false;
}
}
public class Activities
{
public static async Task<bool> Fish(int ID)
{
await Task.Delay(1000);//does not crash here
return true;
}
}

(A)wait for class to finish instantiate

I try to wait for the class to be finished with instantiate.
My architecture is the following. Cook is inheriade from CookChief.
And if I instantiate cook, CookChief is creating himself, but CookChief is calling 1 other class named Cookhelper the cookhelper is waiting for a input and for this input method i want to wait in Cook.
The thing is iam creating this in MVVM Galasoft and my entry point is the CookViewmodel, with a relaycommand.
In the code below you can see my architecture. To say it short I want to wait until this bool processed = await Task.Run(() => ValidateForDeviceId()); is finished.
My first step was to outsource the constructer of each class. And create a init method.
This is my code:
public CookViewModel()
{
startCookButtonCommand = new RelayCommand(Cook);
}
private async Task Cook()
{
cook.Init();
}
public class Cook : CookChief
{
public Cook()
{
}
public async Task Init()
{
await this.CookChiefInit();
//here I want to wait until CookChiefInit is finished
Cooking();
}
public void Cooking()
{
MessageBox.Show("Input received");
}
}
Now the Cookchief:
public Cookchief()
{
}
protected async Task CookchiefInit()
{
this.Cookhelper = new Cookhelper();
Cookhelper.CookHelperInit();
}
And in the CookHelper we do this:
public CookHelper()
{
}
public void CookHelperInit()
{
this.driverWindow = new DriverWindow();
startProc();
}
private async void startProc()
{
ShowOrCloseDriverWindow(true);
//this is the task what we wait for before we can repeat
bool processed = await Task.Run(() => ValidateForDeviceId());
if(processed)
{
ShowOrCloseDriverWindow(false);
}
else
{
MessageBox.Show("DriverError");
}
}
private bool ValidateForDeviceId()
{
for (; ; )
{
this.deviceId = Input.deviceId;
if (deviceId > 0)
{
break;
}
}
return true;
}
Per the discussion in the comments, the problem here was that the initialization routine mixed synchronous and asynchronous methods and calls. Additionally, some async methods were called without the await keyword. The solution was to make all calls asynchronous and await them.
cook.Init() needs an await:
private async Task Cook()
{
await cook.Init();
}
In CookchiefInit(), the CookHelperInit() call needs to be awaited:
protected async Task CookchiefInit()
{
this.Cookhelper = new Cookhelper();
Cookhelper.CookHelperInit();
}
In order to await CookHelperInit(), it needs to be made asynchronous. The startProc() call is to an async method, so it must also be awaited:
public async Task CookHelperInit()
{
this.driverWindow = new DriverWindow();
await startProc();
}

Async wait for multiple threads to finish

I have a code block which is eventually accessed by multiple threads. I search for an up to date async mechanism to continue executing when all threads have passed.
Currently I do the following with a CountDownEvent which works just fine (without async support).
public class Watcher
{
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
private readonly CountdownEvent _isUpdating = new CountdownEvent(1);
private readonly IActivity _activity;
public Watcher([NotNull] IActivity activity)
{
_activity = activity ?? throw new ArgumentNullException(nameof(activity));
_activity.Received += OnReceived;
}
private void OnReceived(IReadOnlyCollection<Summary> summaries)
{
_isUpdating.AddCount();
try
{
// Threads processing
}
finally
{
_isUpdating.Signal();
}
}
private void Disable()
{
_activity.Received -= OnReceived;
_isUpdating.Signal();
/* await */ _isUpdating.Wait();
}
}
Do I need to use any of those AsyncCountdownEvent implementations or is there any other built-in mechanism? I already thought about using a BufferBlock because it has async functionality but I think it's a bit overkill.
Additional to the comments:
IActivity is a WebService call (but shouldn't effect the implementation on top or vice versa)
public async Task Start(bool alwayRetry = true, CancellationToken cancellationToken = new CancellationToken())
{
var milliseconds = ReloadSeconds * 1000;
do
{
try
{
var summaries = await PublicAPI.GetSummariesAsync(cancellationToken).ConfigureAwait(false);
OnSummariesReceived(summaries);
}
catch (Exception ex)
{
Log.Error(ex.Message);
OnErrorOccurred(ex);
}
await Task.Delay(milliseconds, cancellationToken).ConfigureAwait(false);
// ReSharper disable once LoopVariableIsNeverChangedInsideLoop
} while (alwayRetry);
}
It's not clear the IActivity signatures; but you can wait for a range of tasks to be completed:
class MultiAsyncTest {
Task SomeAsync1() { return Task.Delay(1000); }
Task SomeAsync2() { return Task.Delay(2000);}
Task EntryPointAsync() {
var tasks = new List<Task>();
tasks.Add(SomeAsync1());
tasks.Add(SomeAsync2());
return Task.WhenAll(tasks);
}
}
What's IActivity's signature? Does it support Task? Or you are using Thread? More explanation would help to a more specified answer.

Why is this CancellationToken getting cancelled?

It seems like right after I call my first async method (GetBar() in this example), the CancellationToken's IsCancellationRequested is set to true, but I don't want that and don't understand why it's happening.
This is in an Azure Cloud Service worker role, if that matters.
public class WorkerRole : RoleEntryPoint
{
private CancellationTokenSource cancellationTokenSource;
private Task runTask;
public override void Run()
{
this.cancellationTokenSource = new CancellationTokenSource();
this.runTask = Task.Run(() => Foo.Bar(this.cancellationTokenSource.Token), this.cancellationTokenSource.Token);
}
public override void OnStop()
{
this.cancellationTokenSource.Cancel();
try
{
this.runTask.Wait();
}
catch (Exception e)
{
Logger.Error(e, e.Message);
}
base.OnStop();
}
// ... OnStart omitted
}
public static class Foo
{
public static async Bar(CancellationToken token)
{
while (true)
{
try
{
token.ThrowIfCancellationRequested();
var bar = await FooService.GetBar().ConfigureAwait(false);
// Now token.IsCancellationRequested == true. Why? The above call does not take the token as input.
}
catch (OperationCanceledException)
{
// ... Handling
}
}
}
}
I've successfully used CancellationTokens once before in another project and I use a similar setup here. The only difference I'm aware of is that this is in an Azure Cloud Service. Any idea why IsCancellationRequested is getting set to true?
It appears OnStop was called while you where awaiting for FooService.GetBar() to complete. Perhaps add some form of logging to see if OnStop is called between the token.ThrowIfCancellationRequested(); and after the var bar = await ... returns to confirm.
That is what is causing the token to be canceled.
To solve the problem you need to make sure the overridden Run method does not return till the work is complete.
public override void Run()
{
this.cancellationTokenSource = new CancellationTokenSource();
this.runTask = Task.Run(() => Foo.Bar(this.cancellationTokenSource.Token), this.cancellationTokenSource.Token);
this.runTask.Wait(); //You may need a try/catch around it
}

Running a long-running Task within a Windows Service

I have written a Windows Service project which hosts a long-running message pump task which is meant to run for the duration of the service. When the service starts, it starts the task. When the service stops, it stops the task:
void OnStart()
{
MessagePump.Start();
}
void OnStop()
{
MessagePump.Stop();
}
Where MessagePump.Start does a Task.Factory.StartNew, and MessagePump.Stop signals the task to stop and does a Wait().
So far so good, but I'm wondering how best to handle faults. If the task has an unhandled exception, I'd want the service to stop but since nothing is typically Wait-ing on the task, I imagine it'll just sit doing nothing. How can I elegantly handle this situation?
UPDATE:
The consensus seems to be using 'await' or ContinueWith. Here is how I'm currently coding my Start method to use this:
public async static void Start()
{
this.state = MessagePumpState.Running;
this.task = Task.Factory.StartNew(() => this.ProcessLoop(), TaskCreationOptions.LongRunning);
try
{
await this.task;
}
catch
{
this.state = MessagePumpState.Faulted;
throw;
}
}
Make you MessagePump.Start() method return the task. Then
MessagePump.Start().ContinueWith(t =>
{
// handle exception
},
TaskContinuationOptions.OnlyOnFaulted);
UPDATE:
I would do the next:
private MessagePump _messagePump;
async void OnStart()
{
this._messagePump = new MessagePump();
try
{
// make Start method return the task to be able to handle bubbling exception here
await _messagePump.Start();
}
catch (Exception ex)
{
// log exception
// abort service
}
}
void OnStop()
{
_messagePump.Stop();
}
public enum MessagePumpState
{
Running,
Faulted
}
public class MessagePump
{
private CancellationTokenSource _cancallationTokenSrc;
private MessagePumpState _state;
public async Task Start()
{
if (_cancallationTokenSrc != null)
{
throw new InvalidOperationException("Task is already running!");
}
this._state = MessagePumpState.Running;
_cancallationTokenSrc = new CancellationTokenSource();
var task = Task.Factory.StartNew(() => this.ProcessLoop(_cancallationTokenSrc.Token), _cancallationTokenSrc.Token);
try
{
await task;
}
catch
{
this._state = MessagePumpState.Faulted;
throw;
}
}
public void Stop()
{
if (_cancallationTokenSrc != null)
{
_cancallationTokenSrc.Cancel();
_cancallationTokenSrc = null;
}
}
public void ProcessLoop(CancellationToken token)
{
// check if task has been canceled
while (!token.IsCancellationRequested)
{
Console.WriteLine(DateTime.Now);
Thread.Sleep(1000);
}
}
}
You can try something like this :
void OnStart()
{
MessagePump.StartAsync();
MessagePump.ErrorEvent += OnError();
}
Then your StartAsync will look something like:
public async Task StartAsync()
{
// your process
// if error, send event to messagePump
}
And if you decide to use Tasks, then it is better to use Task.Run and not Task.Factory.StartNew()

Categories