如何创建异步方法

Pra*_*dda 51 c# delegates asynchronous

我在C#app中有简单的方法,它从FTP服务器中挑选文件并解析它并将数据存储在DB中.我希望它是异步的,以便用户在App上执行其他操作,一旦完成解析,他必须得到消息"解析完成".

我知道它可以通过异步方法调用实现,但我不知道该怎么做才能有人帮助我吗?

Cal*_*ers 75

您需要使用委托及其BeginInvoke包含的方法异步运行另一个方法.在委托运行的方法结束时,您可以通知用户.例如:

class MyClass
{
    private delegate void SomeFunctionDelegate(int param1, bool param2);
    private SomeFunctionDelegate sfd;

    public MyClass()
    {
        sfd = new SomeFunctionDelegate(this.SomeFunction);
    }

    private void SomeFunction(int param1, bool param2)
    {
        // Do stuff

        // Notify user
    }

    public void GetData()
    {
        // Do stuff

        sfd.BeginInvoke(34, true, null, null);
    }
}
Run Code Online (Sandbox Code Playgroud)

请阅读http://msdn.microsoft.com/en-us/library/2e08f6yc.aspx

  • 请注意,不是声明和使用`SomeFunctionDelegate`,您可以使用`Action <int,bool>`,类似地使用`Func <Type1,Type2,ReturnType>`用于非空的方法. (18认同)
  • new Action <int,string>(MethodName).BeginInvoke(1,"text",null,null); (2认同)

Zai*_*Ali 19

试试这个方法

public static void RunAsynchronously(Action method, Action callback) {
    ThreadPool.QueueUserWorkItem(_ =>
    {
        try {
            method();
        } 
        catch (ThreadAbortException) { /* dont report on this */ } 
        catch (Exception ex) {
        }
        // note: this will not be called if the thread is aborted
        if (callback!= null) callback();
    });
}
Run Code Online (Sandbox Code Playgroud)

用法:

RunAsynchronously( () => { picks file from FTP server and parses it}, 
       () => { Console.WriteLine("Parsing is done"); } );
Run Code Online (Sandbox Code Playgroud)


Joh*_*ers 6

每当你做异步的事情时,你就会使用一个单独的线程,一个新线程,或一个从线程池中获取的线程.这意味着您异步执行的任何操作都必须非常小心与其他线程的交互.

一种方法是将异步线程的代码(称为线程"A")及其所有数据放入另一个类(称为类"A").确保线程"A"仅访问"A"类中的数据.如果线程"A"只接触类"A",并且没有其他线程接触类"A"的数据,那么问题就少了一个:

public class MainClass
{
    private sealed class AsyncClass
    {
        private int _counter;
        private readonly int _maxCount;

        public AsyncClass(int maxCount) { _maxCount = maxCount; }

        public void Run()
        {
            while (_counter++ < _maxCount) { Thread.Sleep(1); }
            CompletionTime = DateTime.Now;
        }

        public DateTime CompletionTime { get; private set; }
    }

    private AsyncClass _asyncInstance;
    public void StartAsync()
    {
        var asyncDoneTime = DateTime.MinValue;
        _asyncInstance = new AsyncClass(10);
        Action asyncAction = _asyncInstance.Run;
        asyncAction.BeginInvoke(
            ar =>
                {
                    asyncAction.EndInvoke(ar);
                    asyncDoneTime = _asyncInstance.CompletionTime;
                }, null);
        Console.WriteLine("Async task ended at {0}", asyncDoneTime);
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,AsyncClass从外部触及的唯一部分是它的公共接口,而其中唯一的部分是数据CompletionTime.请注意,只有在异步任务完成后才会触及此操作.这意味着没有其他任何东西可以干扰任务内部工作,并且它不会干扰任何其他事情.

  • 异步任务完成后,不会打印"异步任务以{0}结束"字符串... (2认同)
  • Plz更正你的陈述"任何时候你做异步的事情,你都在使用一个单独的线程".这是错误的.检查[C#5.0中的异步第四部分:这不是魔术](http://blogs.msdn.com/b/ericlippert/archive/2010/11/04/asynchrony-in-c-5-0-part-four-它-S-未magic.aspx) (2认同)

tan*_*ius 4

这里有两个关于 C# 中线程的链接

我开始阅读有关BackgroundWorker 类的内容