.NET: a mechanism for synchronizing long-running tasks

Description of the problem : you are writing a library that contains some algorithms / tasks that can take a lot of time for various reasons: computing, file system, network communication, etc. You want to be able to:

  • Send some information about the progress of the task (progress, activity logging, etc.).
  • You have a way to abort the task before completion if any external signal or property has been set.

I implemented a structure for this, but it requires that all such tasks reference the assembly containing this structure.

My question is: is there already a built-in mechanism in the .NET framework (3.5 or lower) for the problem described above?

I know that I can use events, but that would mean that long-running tasks should expose events that, I think, are overhead. Ideally, I want to have a framework that hides multithreading problems and is dependency-friendly, but will not depend on an additional user assembly and will not pollute the original interface.

I hope I have described the problem well enough. If not, I can publish some sample interfaces from my own structure.

UPDATE : OK, I think a little clarification is needed for my description of the problem :). When I say "long-term," I do not mean "long" in the sense of a workflow. I am working on a WinForms mapping application that does all kinds of things, like creating contours of terrain . To do this, you first need to download the altitude data files from the FTP server, unzip them, and then perform some calculations. I wrote the code for this a long time ago, but in order to make it more convenient for the graphical interface, I need to perform a retro-check of various checks - for example, if I find that the user clicked the Abort button and stopped the process.

So, basically my concern is this: how to write code that later (if ever at all) will be used in a GUI environment, where you cannot just run everything in the main GUI thread and freeze the entire application. The challenge is to find a way to make your code suitable for GUI purposes without tying it to a specific GUI platform.

+7
multithreading synchronization user-interface c # asynchronous
source share
4 answers

This is similar to the Windows Workflow Foundation .

+6
source share

Take a look at the saga pattern. It is not built into the framework, but can be implemented. Alternatively, both NServiceBus and MassTransit have an implementation of this. Arnon RGO has a project from his book (will it ever be completed) describing it here .

In my experience, working with NServiceBus is much simpler than WF, and also more powerful (although I did not look at WF 4, which by all descriptions is an almost complete rework of WF, since Microsoft recognized this error).

Even if you do not want to use a framework such as NServiceBus or MassTransit, the template itself is worth a look, as it approaches your problem space very close to what you described.

+2
source share

It depends on how complex your system is. For relatively simple problems, you could probably better use the BackgroundWorker class from .NET 2.0. It maintains a progress report using the OnProgressChanged event, and also supports canceling a background task using the CancelAsync method.

The class is event driven, but since this is already part of the class, I don’t think this is overhead for you:

 var bw = new BackgroundWorker(); bw.DoWork += new DoWorkEventHandler(DoWork); bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(RunWorkerCompleted); bw.ProgressChanged += new ProgressChangedEventHandler(ProgressChanged); 
  • The DoWork method DoWork executed to start the background task (it can report the progress by calling bw.ReportProgress and check the pending cancellation using bw.CancellationPending ).

  • The RunWorkerCompleted method executes in the GUI thread when the operation completes (which gives you a good way to synchronize without worrying about concurrency)

  • The ProgressChanged event is fired whenever your DoWork method reports some changes in progress.

For simpler problems, I believe that you could represent your tasks as background workers.

+1
source share

I prefer to use callback methods to signal the UI thread when something is done or progress needs to be updated. You can pass complex objects, and a callback can return a value if it should signal a worker thread. And you are allowed to set some callbacks depending on how much you should answer your employees.

0
source share

All Articles