简体   繁体   中英

Async methods in C#

I have several process that need to run in the background of a Windows Forms application, because they take too much time and I do not want to freeze the user interface until they completely finish, I would like to have an indicator to show the process of each operation, so far I have a form to show the progress of each operation but my operations run synchronously.

So my question is what is the easiest way to run these operation (that access the database) async??

I forgot one important feature that the application requires, the user will have the option to cancel any operation at any time. I think this requirement complicates the application a lot, at least with my current skills, so basically I would like to enphatize that I need a solution easy to understand, and easy to implement. i am aware there will be good practices to follow but at this point I would like some code working later I with more time I would refactor the code

.NET 4 added the Task Parallel Library , which provides a very clean mechanism for making synchronous operations asynchronous.

It allows you to wrap the sync operation into a Task , which you can then either wait on, or use with a continuation (some code that executes when the task completes).

This will often look something like:

Task processTask = Task.Factory.StartNew(() => YourProcess(foo, bar));

Once you have the task, you have quite a few options, including blocking:

// Do other work, then:
processTask.Wait(); // This blocks until the task is completed

Or, if you want a continuation (code to run when it's complete):

processTask.ContinueWith( t => ProcessCompletionMethod());

You can also use this to combine multiple asynchronous operations, and complete when any or all of them are finished, etc.

Note that using Task or Task<T> in this way has another huge advantage - if you later migrate to .NET 4.5, your API will work as-is, with no code changes, with the new async/await language features coming in C# 5.

I forgot one important feature that the application requires, the user will have the option to cancel any operation at any time.

The TPL was also designed, from it's inception, to work nicely in conjunction with the new cooperative cancellation model for .NET 4. This allows you to have a CancellationTokenSource which can be used to cancel any or all of your tasks.

Well in C# there are several ways to accomplish this

Personally I would recommend you to try the Reactive Extensions

http://msdn.microsoft.com/en-us/data/gg577609.aspx

You can actually do something like this:

https://stackoverflow.com/a/10804404/1268570

I created this for you, this is really easy although it is not thread-safe but this would be a good start point

In a form

var a = Observable.Start(() => Thread.Sleep(8000)).StartAsync(CancellationToken.None);
var b = Observable.Start(() => Thread.Sleep(15000)).StartAsync(CancellationToken.None);
var c = Observable.Start(() => Thread.Sleep(3000)).StartAsync(CancellationToken.None);

Manager.Add("a", a.ObserveOn(this).Subscribe(x => MessageBox.Show("a done")));
Manager.Add("b", b.ObserveOn(this).Subscribe(x => MessageBox.Show("b done")));
Manager.Add("c", c.ObserveOn(this).Subscribe(x => MessageBox.Show("c done")));

private void button1_Click(object sender, EventArgs e)
{
    Manager.Cancel("b");
}

Manager utility

public static class Manager
{
    private static IDictionary<string, IDisposable> runningOperations;

    static Manager()
    {
        runningOperations = new Dictionary<string, IDisposable>();
    }

    public static void Add(string key, IDisposable runningOperation)
    {
        if (runningOperations.ContainsKey(key))
        {
            throw new ArgumentOutOfRangeException("key");
        }

        runningOperations.Add(key, runningOperation);
    }

    public static void Cancel(string key)
    {
        IDisposable value = null;
        if (runningOperations.TryGetValue(key, out value))
        {
            value.Dispose();
            runningOperations.Remove(key);
        }
    }

If the ORM/database API doesn't come with async methods itself, have a look at the BackgroundWorker Class . It supports both cancellation ( CancelAsync / CancellationPending ) and progress reporting ( ReportProgress / ProgressChanged ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM