0

I have two situations that I'm not sure how to resolve properly. First is a task that runs for as long as the application. Currently, I have a construction like this:

this.task = this.joinableTaskFactory.RunAsync(async () => await this.TaskProcedureAsync().ConfigureAwait(false), JoinableTaskCreationOptions.LongRunning);

Here TaskProcedureAsync is usually a loop until the application end signal is received and inside of it is await of some sort that provides a job to complete (e.g. from an async queue), when it arrives, it is processed and then it waits again for the next job.

Here I'm not sure if running with JoinableTaskCreationOptions.LongRunning is a correct solution for such a task. In DisposeCoreAsync then I await this joinable task:

            await this.task.JoinAsync().ConfigureAwait(false);

and then do the rest of the disposal work. So the question here, if this is right thing to do in such scenario or if there is a better way to run such long running async task. This seems to work fine as it is, just not sure if it is optimal regarding the internal management of threads. There are not that many of these loops in the application, up to 30 is a reasonable expectation for my application.

The follow up problem I am quite sure that does not work well as I have it now. Besides those loop tasks that I have that run for as long as the application, I also have a bigger number of long running task that are supposed to be strictly time limited. Currently I use TplExtensions.WithTimeout extension:

result = await script.InitializeAsync().WithTimeout(TimeSpan.FromSeconds(ScriptInitializationTimeoutSeconds)).ConfigureAwait(false);

Basically I am running an untrusted code that must be stopped after certain limit. Now the problem is that WithTimeout does not stop the task itself, only throws exception after the time is out. The question here is how to implement this properly? I was thinking that if the code is to be stopped, it should be run in its own thread as a thread can be killed while task can not. But then I've read here that such an approach would not work because I could only execute synchronous code in such a thread and not async code.

Is there any way to kill the task then? Can I for example kill the thread that currently executes the task? Or how is this done properly?

Wapac
  • 4,058
  • 2
  • 20
  • 33
  • 1
    Is there a reason that you are using a [`JoinableTaskFactory`](https://learn.microsoft.com/en-us/dotnet/api/microsoft.visualstudio.threading.joinabletaskfactory) instead of a simple `TaskFactory`? Btw I would suggest to add the [visual-studio-sdk](https://stackoverflow.com/questions/tagged/visual-studio-sdk) tag in the question. – Theodor Zoulias Jan 29 '21 at 18:04
  • Regarding the problems associated with aborting threads: [What's wrong with using Thread.Abort()](https://stackoverflow.com/questions/1559255/whats-wrong-with-using-thread-abort). Btw be aware that the `Thread.Abort` is not supported in .NET 5 and .NET Core. – Theodor Zoulias Jan 29 '21 at 18:09
  • Thanks, added the suggested tag. As for Thread.Abort - while I am running untrusted code in general that can loop forever, I do control which libraries it uses, so I can prevent any kind of "defense". – Wapac Jan 29 '21 at 18:26
  • As for JoinableTaskFactory - the idea to use it comes from https://github.com/Microsoft/vs-threading/blob/main/doc/analyzers/VSTHRD003.md – Wapac Jan 29 '21 at 18:32
  • 1
    AFAIK the experts suggest to run untrusted code in a separate process. Not even in a separate `AppDomain`. And that's pretty much all I know about executing untrusted code. :-) – Theodor Zoulias Jan 29 '21 at 18:36
  • I was not aware that it is not available in .NET 5. That disqualifies any solution with threads I guess. – Wapac Jan 29 '21 at 18:38
  • @Wapac - Any solution using `Thread.Abort()` in any version of .NET is either dangerous and shouldn't be done or cannot be called as `Abort()` has been removed. The only safe option is to launch a new process. – Enigmativity Feb 01 '21 at 04:25

0 Answers0