How to make 2 tasks run simultaneously in a UWP background app? - c#

I need help running my UWP background app deployed on my Raspberry Pi (hosting Windows 10 IOT Core).
It's almost working but I got a tricky issue... Let me explain:
The app has 2 functionalities:
A Web Server that receives http requests and do some processing according to parameters. (based on this link)
A repeating task that is executed every X minutes (X varies from 10 to 60).
Both functionalities work well if executed seperately but I need them to run simultaneously. I'm rather new to UWP & Raspberry so maybe there's something I'm missing...
Is it a matter of thread conflict?
Is a background task on a raspberry limited to a single thread (so the first/last process executed wins)?
Do all classes need to be "sealed" (microsofts's doc says so but not the example they provide)?
I tought about splitting the project into two independant deployable tasks and I believe it would work but I need the webserver task to control (START/PAUSE/STOP) the repeating task.
I think communication between them could be feasable (using this way) but I'm looking for the simplest/fastest solution here.
Here's the stripped down code (the 3 classes are in separate files):
App class:
public sealed class StartupTask : IBackgroundTask
{
private static BackgroundTaskDeferral _Deferral = null;
public async void Run(IBackgroundTaskInstance taskInstance)
{
_Deferral = taskInstance.GetDeferral();
var webserver = new WebServer();
await ThreadPool.RunAsync(workItem => { webserver.Start(); });
StartRepeatingTask();
}
}
Web server class:
internal class WebServer
{
private const uint BUFFER_SIZE = 8192;
public async void Start()
{
var listener = new StreamSocketListener();
await listener.BindServiceNameAsync("1537");
listener.ConnectionReceived += async (sender, args) =>
{
// Do some stuff
...
Processing.StopProcess();
}
}
}
Processing class
public class Processing
{
private static Task myTask = null;
private static CancellationTokenSource taskCancellation = new CancellationTokenSource();
public static void StartRepeatingTask()
{
taskCancellation = new CancellationTokenSource();
myTask = Task.Run(() => AutoProcess(), taskCancellation.Token);
}
public static void AutoProcess()
{
Process();
myTask = Task.Delay(GetDelayToUse(DELAY_SET_LIST))
.ContinueWith(t => AutoProcess(), taskCancellation.Token);
}
public static void Process()
{
// Do some other stuff
}
public static void StopProcess()
{
taskCancellation.Cancel();
}
}

The two task can run in a background app simultaneously.
Is it a matter of thread conflict?
If there are no commitications or shared data between the two task, there will be no confilct. The important thing is that you need to pay attention to the synchronization of data. If you use a list or queue to share the data between the two threads, you should use the concurrency object. Please refer to ConcurrentQueue example, ConcurrentQueue represents a thread-safe.
Is a background task on a raspberry limited to a single thread (so the
first/last process executed wins)?
Once a background applications are deployed and configured, these applications launch at machine startup and run continuously without any process lifetime management resource use limitations. There are some limitations about background task, but it is not limited to a single thread. More information here. Here you need to differentiate the background application on Windows IoT Core and task.
Do all classes need to be "sealed" (microsofts's doc says so but
not the example they provide)?
Yes, the background task class itself—and all other classes in the background task project—need to be public classes that are sealed (or final). It applies to the background tasks which inherited from interface IBackgroundTask, but not the classes are using for normal thread.

Related

One thread switching between two tasks

I have two threads communicating with each other. When one thread works second is blocked and vice versa. Is it possible to have done everything on one thread without changing the application's logic?
Example:
Robot (thread 1) is communicating with the simulator of the environment for robots (thread 2).
The robot chooses an action to take and then his thread is interrupted and the environment's thread is waked up. The environment simulator modifies the robot's environment based on the action the robot has taken. It sends back to the robot (potentially partial) information what the environment looks like. Robots thread awakens and environment thread is blocked until the robot takes the next action.
Both Robot and the environment simulator have complicated logic consisting of their own call stack.
Robot's program can call method environment.Act(action) from various places in various methods. The environment's simulator can call ReadAction() and SendResponse also from various places.
Since the two threads never run simultaneously is it possible to somehow use asynchronous programming or something in c# to keep everything in one thread?
I want both the robot and its environment to be callers of communication methods. I don't want to invert the logic to make them callees.
Here is what I tried:
class Robot
{
public async Task RunAsync(RobotsEnvironment environment)
{
Belief estimatedStateRepresentation = new Belief();
while (true)
{
RobotsAction action = estimatedStateRepresentation.BestAction();
Observation observation = await environment.Act(action);
Console.WriteLine("Robot : " + System.Threading.Thread.CurrentThread.ManagedThreadId);
estimatedStateRepresentation = estimatedStateRepresentation.Update(action, observation);
}
}
}
class RobotsEnvironment
{
MyConcurrentQueue<RobotsAction> actions = new MyConcurrentQueue<RobotsAction>();
MyConcurrentQueue<Observation> observations = new MyConcurrentQueue<Observation>();
public Task<Observation> Act(RobotsAction action)
{
actions.Post(action);
return observations.ReceiveAsync();
}
public async Task RunAsync(State initialState)
{
State state = initialState;
while (true)
{
RobotsAction action = await actions.ReceiveAsync();
Console.WriteLine("Environment: " + System.Threading.Thread.CurrentThread.ManagedThreadId);
state = state.Update(action);
observations.Post(state.GenerateObservation());
}
}
}
Since the robot never runs simultaneously with its environment. I hoped that the ManagedThreadId written in the output will be constant. Unfortunately. It seems that both robot and it's environment have their own threads and that they sometimes move to other threads.
I suspect that it may be caused by the way I implemented synchronization:
internal class MyConcurrentQueue<T>
{
readonly object lockObject = new object();
SemaphoreSlim semaphore;
Queue<T> queue = new Queue<T>();
public MyConcurrentQueue()
{
this.semaphore = new SemaphoreSlim(0);
}
public async Task<T> ReceiveAsync()
{
await semaphore.WaitAsync();
lock (lockObject)
{
if (queue.Count == 0 && receivingFinished)
throw new TaskCanceledException();
return queue.Dequeue();
}
}
public void Post(T item)
{
lock (lockObject)
{
queue.Enqueue(item);
semaphore.Release();
}
}
}
Is it possible to do it better to keep everything in one thread?
What is my motivation? I would just have better feeling it it would be in one thread. Does it have some advantages? I do not need it for any purpose. Shoud I even care about it? Should I somehow try to minimize the synchronization overhead?
EDIT:
This is the way how I start the threads:
Task.WaitAll(agent.RunAsync(environment), environment.RunAsync(initialState));

C# email checker plugin: make better-behaved

In C# (Net4.5, Win10) I wrote an email checker plugin. It handles Gmail/POP/IMAP. It works. But the plugin often freezes the app for a long time, if there's a connection problem etc. In C#, how can I "wrap" (delegate to a separate thread?) the GetEmails() function so that 1) it doesn't perceptibly "freeze" the rest of the app, 2) times out if it can't do its job within ~5 sec?
private static void GetEmails(int i) {
// if Gmail
cred = new NetworkCredential(user,password);
request = (HttpWebRequest)WebRequest.Create(atomURL);
try {
response = (HttpWebResponse)request.GetResponse();
...
// if POP
try {
pop.Connect();
...
// if IMAP
try {
imap.Connect();
...
}
Your app freezes because all the operation is happening on main thread including UI. While long operation is in progress, main thread is busy doing stuff thus UI becomes unresponsive.
For this multi thread/parallel programming is done to delegate long operations on to a different thread.
There are multiple approaches to do multi threaded programming some are:
Task Parallel Library(TPL) (recommended) or Background Worker
Task Parallel Library(TPL) visit link
Background Worker visit link
If someone has the same issue. Most of the "async" docs promise to be simple, then balloon into bloat. Also, in an existing project, the "async/await" logic can get convoluted, require cascading changes, and you can get stuck on functions without GetAwaiter() (like GetResponse()). Here's a simple task wrapper I made for my existing function (with time-out).
Asynchronous programming in C-Sharp
var cts = new CancellationTokenSource();
var token = cts.Token;
cts.CancelAfter(5000);
Task task = Task.Run(() => { GetEmails(i, cts); }, token);
private static void GetEmails(int i, CancellationToken token) {
try {
...
token.ThrowIfCancellationRequested();
} catch (Exception ex) {
//will be thrown if cts.IsCancellationRequested
return;
}
}

Handling WF 4.0 long running activity using TPL

I created an activity which executes a web request and stores the result into the database. Usually this process takes about 1 hour and it makes workflow engine to behave abnormally. I found out that for these long running activities I should write some different code so that the workflow engine thread won't be blocked.
Studying some blogs about writing long running activities I understand that I should use Bookmark concept. But I didn't any solution using TPL and Task.
Is this code correct for handling a long running activity using Tasks?
public sealed class WebSaveActivity : NativeActivity
{
protected override void Execute(NativeActivityContext context)
{
context.CreateBookmark("websave", (activityContext, bookmark, value) =>
{
});
Task.Factory.StartNew(() =>
{
GetAndSave(); // This takes 1 hour to accomplish.
context.RemoveBookmark("websave");
});
}
protected override bool CanInduceIdle
{
get
{
return true;
}
}
}
No, that is not the way bookmarks should be used. A bookmark is used when the workflow has to wait for input from an external process.
For example: I have a document approval workflow and at some point in time the workflow has to wait for a human reviewer to give an OK on the document. Instead of keeping the workflow instance in memory the workflow will be idled and activated again by the runtime when ResumeBookmark is called.
In your situation your workflow cannot be idled since it has an operation running in its context. That operation is your task that, by the way, is a fire-and-forget tasks so critical failures cannot be handled by the WF.
Now, for a possible solution you might consider to have an other process call the GetAndSave method and have that process ultimately call the ResumeBookmark on the WF so the workflow can be idled by the runtime. That process could even be the same process that hosts your workflow.
For an example see this blogpost. Just image that instead of waiting for a human to enter something in the console your long running task is performed.
You did not specify what comes after your activity but do note that it is possible to return data back to the workflow when the bookmark is resumed. So any result of the GetAndSave, even if it is just an error code you can use to decide how to further go along with the other activities in your workflow.
Hope this makes sense to you and you see what I try to outline as a possible solution.
EDIT
A quick note about using Tasks or async/await in WF. There are AFAIK no methods to override that return Tasks so you either have to make them block by using .Wait() or .Result or forget about it. Because if you cannot await them bad things will happen during workflow execution because other activities might be started before the one using Tasks has completed its work.
When the WF runtime was developed the whole concept of Tasks was still very young so the WF runtime did not / does not cater for them.
EDIT 2:
example implementation (Based on this excellent official documentation)
Your activity will be almost empty:
public sealed class TriggerDownload : NativeActivity<string>
{
[RequiredArgument]
public InArgument<string> BookmarkName { get; set; }
protected override void Execute(NativeActivityContext context)
{
// Create a Bookmark and wait for it to be resumed.
context.CreateBookmark(BookmarkName.Get(context),
new BookmarkCallback(OnResumeBookmark));
}
protected override bool CanInduceIdle
{
get { return true; }
}
public void OnResumeBookmark(NativeActivityContext context, Bookmark bookmark, object obj)
{
// When the Bookmark is resumed, assign its value to
// the Result argument. (This depends on whether you have a result on your GetData method like a string with a result code or something)
Result.Set(context, (string)obj);
}
}
It signals the workflow runtime that the workflow can be idled and how it can be resumed.
Now, for the workflow runtime configuration:
WorkflowApplication wfApp = new WorkflowApplication(<Your WF>);
// Workflow lifecycle events omitted except idle.
AutoResetEvent idleEvent = new AutoResetEvent(false);
wfApp.Idle = delegate(WorkflowApplicationIdleEventArgs e)
{
idleEvent.Set();
};
// Run the workflow.
wfApp.Run();
// Wait for the workflow to go idle before starting the download
idleEvent.WaitOne();
// Start the download and resume the bookmark when finished.
var result = await Task.Run(() => GetAndSave());
BookmarkResumptionResult result = wfApp.ResumeBookmark(new Bookmark("GetData"), result);
// Possible BookmarkResumptionResult values:
// Success, NotFound, or NotReady
Console.WriteLine("BookmarkResumptionResult: {0}", result);
I just saw your related question here: How to write a long running activity to call web services in WF 4.0
Another way is to implement your activity is as an AsyncCodeActivity:
namespace MyLibrary.Activities
{
using System;
using System.Activities;
public sealed class MyActivity : AsyncCodeActivity
{
protected override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
{
var delegateToLongOperation = new Func<bool>(this.LongRunningSave);
context.UserState = delegateToLongOperation;
return delegateToLongOperation.BeginInvoke(callback, state);
}
protected override void EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
{
var longOperationDelegate = (Func<bool>) context.UserState;
var longOperationResult = longOperationDelegate.EndInvoke(result);
// Can continue your activity logic here.
}
private bool LongRunningSave()
{
// Logic to perform the save.
return true;
}
}
}
The workflow instance stays in memory, but at the very least the workflow runtime can handle its normal scheduling tasks without one of its threads being taken up by a long running process.

C# .Net - How to make application wait until all threads created in Library are finished

I am trying to create a logging library and things are good until the application shutdown is called. When application shutdown is called, any unfinished thread is killed and the specific log is lost.
As of now application exits even before the first 10 threads are complete. I want help on how to make the application wait until all threads created by library are done.
NOTE:
Requirement I got are like this. Modifications should be only in the class 'Logging' since this will be a library and will be provided to end users. Handling of logging issues during app shutdown must be done within it. This is where I have trouble now.
Alternatively a solution like create an event in logging class to trigger all logging complete, and ask user to call app exit on that event is possible, but that I am trying to avoid since it adds that burden to end user and adds complexity for implementations. There is a possibility they may skip it, which I do not want. I am looking for a solution like user should do 'Logging.AddException(....)' and then forget about it.
Please help. Provide comments if you are not clear about the idea.
Here is the full code abstract which you can put into a console application.
Note: Look for comments in CASE 1 and CASE 2.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace MultithreadKeepAlive
{
class Program
{
static void Main(string[] args)
{
LogLoadTest();
Logging.AddExceptionEntryAsync(new Exception("Last Exception"));
/*
* USE CASE 1: Enable the below lines and you will see how long it is supposed to take.
* Notice that currentDomain_ProcessExit will not trigger if below gets uncommented
*/
//Console.WriteLine("Main thread wait override");
//Console.ReadLine();
}
static void LogLoadTest()
{
//In real world this will be called from any place of application like startup or just after application shutdown is initiated.
//: NOTICE: Unlike the sample here, this will never be on loop and I am not looking for handling multithreads in this class.
// That responsibility I am planning to assign to Logging class.
// AND ALSO the class Logging is going to be in a seperate signed assembly where user of this class ('Program') should not worry about multithreads.
Task t;
for (int i = 0; i < 40; i++)
{
t = Logging.AddExceptionEntryAsync(new Exception("Hello Exception " + i), "Header info" + i);
}
}
}
public class Logging
{
static List<Task> tasks = new List<Task>();
static AppDomain currentDomain;
static Logging()
{
currentDomain = AppDomain.CurrentDomain;
currentDomain.ProcessExit += currentDomain_ProcessExit;
}
public static async Task AddExceptionEntryAsync(Exception ex, string header = "")
{
Task t = Task.Factory.StartNew(() => AddExceptionEntry(ex, header));
tasks.Add(t);
await t;
}
public static void AddExceptionEntry(Exception ex, string header)
{
/* Exception processing and write to file or DB. This might endup in file locks or
* network or any other cases where it will take delays from 1 sec to 5 minutes. */
Thread.Sleep(new Random().Next(1, 1000));
Console.WriteLine(ex.Message);
}
static void currentDomain_ProcessExit(object sender, EventArgs e)
{
Console.WriteLine("Application shutdown triggerd just now.");
Process.GetCurrentProcess().WaitForExit(); //1st attempt.
//Task.WaitAll(tasks.ToArray()); //2nd attempt
while (tasks.Any(t => !t.IsCompleted)) //3rd attempt.
{
}
/* USE CASE 2: IF WORKING GOOD, THIS WILL BE DISPLAYED IN CONSOLE AS LAST
* MESSAGE OF APPLICATION AND WILL WAIT FOR USER. THIS IS NOT WORKING NOW.*/
Console.WriteLine("All complete"); //this message should show up if this work properly
Console.ReadLine(); //for testing purpose wait for input from user after every thread is complete. Check all 40 threads are in console.
}
}
}
You can try
Task.WaitAll(tasks);
This waits for all of the provided Task objects to complete execution.
UPDATE : using async/await
With async and await, we formalize and clarify how asynchronous, non-blocking methods begin and end. An async method can return only void or a Task.
static void Main()
{
// Create task and start it.
// ... Wait for it to complete.
Task task = new Task(AsyncMethod);
task.Start();
task.Wait();
}
public static async void AsyncMethod(){
await AnotherMehod();}
static async Task AnotherMehod() { //TODO}
As of now I myself found a workaround.
/// <summary>
/// Makes the current thread Wait until any of the pending messages/Exceptions/Logs are completly written into respective sources.
/// Call this method before application is shutdown to make sure all logs are saved properly.
/// </summary>
public static void WaitForLogComplete()
{
Task.WaitAll(tasks.Values.ToArray());
}
Step 1: Consider changing to Task.Run() if you do not want the scheduler to be involved. I'm also assuming you want to wait until all async tasks finish.
public static AddExceptionEntry(Exception ex, string header = "")
{
Task t = Task.Factory.StartNew(() => AddExceptionEntry(ex, header));
tasks.Add(t);
WaitForExecutionAsync().ConfigureAwait(true);
}
public static async Task WaitForExecutionAsync()
{
if(tasks.Count >0)
await Task.WhenAll(tasks.ToArray());
// Raise Event.
}
To Block just call this to run sync vs async:
WaitForExecution().GetAwaiter().GetResult();

how to propagate some data to main process from TPL tasks while tasks are running

I have a situation where I create a list of long running tasks which monitors some system/network resources and then sends email, logs into a txt file, and calls a web service when some conditions are met. Then begins monitoring again. These tasks are created in a windows service and hence will be running all the time.
I want them to raise events or something to notify the parent class (which created them) and it will performs the 3 operations i mentioned above instead of each object in tasks doing it by itself.
And how can it be controlled that only a single task uses that parent class's method at a single time. As Email and a web service call is involved, so two concurrent requests may beak the code.
UPDATE
These Watchers are of three types, each implements the following interface.
public interface IWatcher
{
void BeginWatch();
}
Classes that implement are
//this watcher is responsible for watching over a sql query result
public class DBWatcher : IWatcher
{
....
void BeginWatch()
{
//Here a timer is created which contiously checks the SQL query result.
//And would Call SERVICE, send an EMAIL and LOG into a file
Timer watchIterator = new Timer(this._intervalMinutes * 60000);
watchIterator.Elapsed += new ElapsedEventHandler(_watchIterator_Elapsed);
watchIterator.Start();
}
void _watchIterator_Elapsed(object sender, ElapsedEventArgs e)
{
//1. Check Query result
//3. Call SERVICE, send an EMAIL and LOG into a file if result is not as was expected
//I have done the work to this part!
//And I can do the functions as follows .. it should be simple.
//*********************
//SendEmail();
//LogIntoFile();
//CallService();
//But I want the above three methods to be present in one place so i dont have to replicate same functionality in different watcher.
//One approach could be to create a seperate class and wrape the above mentioned functions in it, create an instance of that class here and call them.
//Second option, which I am interested in but dont know how to do, is to have this functionality in the parent class which actually creates the tasks and have each watcher use it from HERE ...
}
....
}
//this watcher is responsible for watching over Folder
public class FolderWatcher : IWatcher
{
....
void BeginWatch()
{
///Same as above
}
....
}
First I create a List from an XML file. This can contain multiple instances of DBWatcher which will continously watch a different query result and FolderWatcher which will continously watch different Folders continously.
After the List is created, I call the following function that I call to create a separate Task. I call this function MANY times to create a different set of watchers.
private void _createWatcherThread(IWatcher wat, CancellationTokenSource cancellationToken)
{
//This represents a watcher that will watch some specific area for any activities
IWatcher watcher = wat.Copy();
bool hasWatchBegin = false;
try
{
//run forever
for (;;)
{
//dispose the watcher and stop this thread if CANCEL token has been issued
if (cancellationToken.IsCancellationRequested)
{
((IDisposable)watcher).Dispose();
break;
}
else if (!hasWatchBegin)
{
//This method of a watcher class creates a timer. which will
//continously check the status after a few minutes... So its the
//timer's elapsed method in Watcher object which will send the mail
//& call service etc to update the admin of current status of the watcher.
//this will be called only once in a watcher!
watcher.BeginWatch();
hasWatchBegin = true;
}
}
}
catch (Exception ex)
{
//Watcher has thrown an exception.
//Again, do the following operations
//*********************
//SendEmail();
//LogIntoFile();
//CallService();
}
}
Provided you make your email, logging & webservice calls threadsafe you can pass references to the code which sends to each of these sinks as a closure (Here's Jon Skeet's excellent explanation of c# closures) into the monitoring tasks. Here's an example where you need to launch multiple tasks:
...
void Email(string message){}
void Log(string message){}
void CallWebService(string message){}
void RunMonitoringTask()
{
var task = Task.TaskFactory.StartNew(() =>
{
string message = Monitor();
if( ShouldNotify(message))
{
Email(mesasge);
Log(message);
CallWebService(message);
}
}
)
}
...
EDIT
vs. an infinite monitor loop triggering tasks when necessary:
...
void Email(string message){}
void Log(string message){}
void CallWebService(string message){}
void Monitor()
{
while(true)
{
string message = Monitor();
if(ShouldNotify(message))
{
var task = Task.TaskFactory.StartNew(() =>
{
Email(mesasge);
Log(message);
CallWebService(message);
}
}
}
)
}
...
As far as how to implement these classes, I'd recomend an approach where each of these sinks accepts the message & then offloads it to it's own processing thread/task to avoid blocking your monitoring tasks & holding up the other notifications.
The Progress class is just perfect for this task. It is a means of allowing a long running process to notify someone (usually the caller) of the current progress of that operation.
Progress<string> progress = new Progress<string>();
progress.ProgressChanged += (s, data) => Console.WriteLine(data);
for (int i = 0; i < 2; i++)
Task.Run(() => DoWork(progress));
public static void DoWork(IProgress<string> progress)
{
int i = 0;
while (true)
{
Thread.Sleep(500);//placeholder for real work
progress.Report(i++.ToString());
}
}
If you have different types of information to report at different times then just pass in multiple IProgress instances to the worker method. (Or, if you are reporting the progress of several types of data at the same time wrap all of the data in a composite object.)
Also note that this is capable of handling the synchronization that you have said that you need. Progress instances, when created, capture the value of SynchronizationContext.Current at the time that it's created, and marshal all of the event handlers for the progress changed event into that sync context. So if your application will already have a context (i.e. a UI context from a desktop application) then you get that for free. If you don't have one (i.e. it's a console application) then you'll need to either manually synchronize the event handler with say a lock, or create your own SynchrnonizationContext to set as the current context.

Categories

Resources