C# 如何创建异步方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1159214/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 09:37:52  来源:igfitidea点击:

How to create an asynchronous method

c#asynchronousdelegates

提问by Prashant Cholachagudda

I have simple method in my C# app, it picks file from FTP server and parses it and stores the data in DB. I want it to be asynchronous, so that user perform other operations on App, once parsing is done he has to get message stating "Parsing is done".

我在我的 C# 应用程序中有一个简单的方法,它从 FTP 服务器中选择文件并解析它并将数据存储在数据库中。我希望它是异步的,以便用户在 App 上执行其他操作,一旦解析完成,他必须收到消息说明“解析完成”。

I know it can achieved through asynchronous method call but I dont know how to do thatcan anybody help me please??

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

回答by tanascius

Here are two links about threading in C#

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

I'd start to read about the BackgroundWorker class

我会开始阅读有关BackgroundWorker 类的信息

回答by Callum Rogers

You need to use delegates and the BeginInvokemethod that they contain to run another method asynchronously. A the end of the method being run by the delegate, you can notify the user. For example:

您需要使用委托及其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);
    }
}

Read up at http://msdn.microsoft.com/en-us/library/2e08f6yc.aspx

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

回答by Callum Rogers

ThreadPool.QueueUserWorkItemis the quickest way to get a process running on a different thread.

ThreadPool.QueueUserWorkItem是让进程在不同线程上运行的最快方法。

Be aware that UI objects have "thread affinity" and cannot be accessed from any thread other than the one that created them.

请注意,UI 对象具有“线程关联性”,不能从创建它们的线程以外的任何线程访问。

So, in addition to checking out the ThreadPool (or using the asynchronous programming model via delegates), you need to check out Dispatchers(wpf) or InvokeRequired(winforms).

因此,除了检查 ThreadPool(或通过委托使用异步编程模型)之外,您还需要检查Dispatchers(wpf) 或InvokeRequired(winforms)。

回答by John Saunders

Any time you're doing something asynchronous, you're using a separate thread, either a new thread, or one taken from the thread pool. This means that anything you do asynchronously has to be very careful about interactions with other threads.

任何时候做异步操作时,都会使用一个单独的线程,可以是新线程,也可以是从线程池中提取的线程。这意味着您异步执行的任何操作都必须非常小心与其他线程的交互。

One way to do that is to place the code for the async thread (call it thread "A") along with all of its datainto another class (call it class "A"). Make sure that thread "A" only accesses data in class "A". If thread "A" only touches class "A", and no other thread touches class "A"'s data, then there's one less problem:

一种方法是将异步线程的代码(称为线程“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);
    }
}

Notice that the only part of AsyncClassthat's touched from the outside is its public interface, and the only part of that which is data is CompletionTime. Note that this is onlytouched after the asynchronous task is complete. This means that nothing else can interfere with the tasks inner workings, and it can't interfere with anything else.

请注意,AsyncClass从外部接触的唯一部分是其公共接口,而唯一的部分是数据CompletionTime。请注意,这在异步任务完成后才会触及。这意味着没有其他东西可以干扰任务的内部运作,也不能干扰其他任何东西。

回答by QueueHammer

In the end you will have to use some sort of threading. The way it basically works is that you start a function with a new thread and it will run until the end of the function.

最后,您将不得不使用某种线程。它的基本工作方式是你用一个新线程启动一个函数,它会一直运行到函数结束。

If you are using Windows Forms then a nice wrapper that they have for this is call the Background Worker. It allows you to work in the background with out locking up the UI form and even provides a way to communicate with the forms and provide progress update events.

如果您使用的是 Windows 窗体,那么他们为此提供的一个很好的包装器称为后台工作器。它允许您在后台工作而无需锁定 UI 表单,甚至提供一种与表单进行通信并提供进度更新事件的方法。

Background Worker

后台工作者

回答by Fischer

In Asp.Net I use a lot of staticmethods for jobs to be done. If its simply a job where I need no responseor status, I do something simple like below. As you can see I can choose to call either ResizeImages or ResizeImagesAsync depending if I want to wait for it to finish or not

在 Asp.Net 中,我使用了很多静态方法来完成工作。如果它只是一份我不需要回应或状态的工作,我会做一些简单的事情,如下所示。如您所见,我可以根据是否要等待它完成来选择调用 ResizeImages 或 ResizeImagesAsync

Code explanation: I use http://imageresizing.net/to resize/crop images and the method SaveBlobPng is to store the images to Azure (cloud) but since that is irrelevant for this demo I didn't include that code. Its a good example of time consuming tasks though

代码说明:我使用http://imageresizing.net/来调整/裁剪图像的大小,而 SaveBlobPng 的方法是将图像存储到 Azure(云),但由于这与本演示无关,因此我没有包含该代码。虽然它是耗时任务的一个很好的例子

private delegate void ResizeImagesDelegate(string tempuri, Dictionary<string, string> versions);
private static void ResizeImagesAsync(string tempuri, Dictionary<string, string> versions)
{
    ResizeImagesDelegate worker = new ResizeImagesDelegate(ResizeImages);
    worker.BeginInvoke(tempuri, versions, deletetemp, null, null);
}
private static void ResizeImages(string tempuri, Dictionary<string, string> versions)
{
    //the job, whatever it might be
    foreach (var item in versions)
    {
        var image = ImageBuilder.Current.Build(tempuri, new ResizeSettings(item.Value));
        SaveBlobPng(image, item.Key);
        image.Dispose();
    }
}

Or going for threading so you dont have to bother with Delegates

或者进行线程处理,这样您就不必理会代表

private static void ResizeImagesAsync(string tempuri, Dictionary<string, string> versions)
{
    Thread t = new Thread (() => ResizeImages(tempuri, versions, null, null));
    t.Start(); 
}

回答by Zain Ali

try this method

试试这个方法

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();
    });
}

Usage:

用法:

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

回答by Piotr Wojcik

.NET got new keyword asyncfor asonchrynous functions. You can start digging at docs.microsoft.com (async). The shortest general howto make function asonchrynous is to change function F:

.NET为异步函数获得了新的关键字async。您可以从docs.microsoft.com (async)开始挖掘。使函数异步的最短一般方法是更改​​函数F

Object F(Object args)
{
    ...
    return RESULT;
}

to something like this:

像这样:

async Task<Object> FAsync(Object args)
{
    ...
    await RESULT_FROM_PROMISE;
    ...
    return RESULT;
}

The most important thing in above code is that when your code approach awaitkeyword it return control to function that called FAsyncand make other computation until promissed value has been returned and procede with rest of code in function FAsync.

上面代码中最重要的一点是,当您的代码使用await关键字时,它会将控制权返回给调用FAsync 的函数并进行其他计算,直到返回承诺值并继续执行函数FAsync 中的其余代码。