Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何以及何时使用&x2018;异步’;和‘;等待&x2019;_C#_.net_Asynchronous_Async Await - Fatal编程技术网

C# 如何以及何时使用&x2018;异步’;和‘;等待&x2019;

C# 如何以及何时使用&x2018;异步’;和‘;等待&x2019;,c#,.net,asynchronous,async-await,C#,.net,Asynchronous,Async Await,据我所知,其中一项主要任务是使代码易于编写和读取,但使用它们是否等同于生成后台线程来执行长时间逻辑 我正在尝试最基本的例子。我在内联添加了一些注释。你能给我澄清一下吗 // I don't understand why this method must be marked as `async`. private async void button1_Click(object sender, EventArgs e) { Task<int> access = DoSomethi

据我所知,其中一项主要任务是使代码易于编写和读取,但使用它们是否等同于生成后台线程来执行长时间逻辑

我正在尝试最基本的例子。我在内联添加了一些注释。你能给我澄清一下吗

// I don't understand why this method must be marked as `async`.
private async void button1_Click(object sender, EventArgs e)
{
    Task<int> access = DoSomethingAsync();
    // task independent stuff here

    // this line is reached after the 5 seconds sleep from 
    // DoSomethingAsync() method. Shouldn't it be reached immediately? 
    int a = 1; 

    // from my understanding the waiting should be done here.
    int x = await access; 
}

async Task<int> DoSomethingAsync()
{
    // is this executed on a background thread?
    System.Threading.Thread.Sleep(5000);
    return 1;
}
//我不明白为什么这个方法必须标记为'async'。
私有异步无效按钮1\u单击(对象发送方,事件参数e)
{
任务访问=DoSomethingAsync();
//任务无关的东西
//从睡眠5秒后到达此线路
//DoSomethingAsync()方法。是否应该立即访问它?
INTA=1;
//据我所知,等待应该在这里完成。
int x=等待访问;
}
异步任务DoSomethingAsync()
{
//这是在后台线程上执行的吗?
系统线程线程睡眠(5000);
返回1;
}

我认为您在
System.Threading.Thread.Sleep中选择了一个不好的例子

async
任务的要点是让它在后台执行而不锁定主线程,例如执行
DownloadFileAsync

System.Threading.Thread.Sleep
不是“完成”的东西,它只是休眠,因此5秒后到达下一行


阅读这篇文章,我认为这是对
async
wait
概念的一个很好的解释:

关于其他答案,请看

更具体地说,在所包含的示例中,它稍微解释了您的情况

下面的Windows窗体示例演示了在 异步方法,WaitAsynchronouslyAsync。对比一下那个人的行为 方法的行为为WaitSynchronous。无需等待 运算符应用于任务,WaitSynchronous同步运行 尽管在其定义中使用了异步修饰符并调用 线。睡在它的身体里

private async void按钮1\u单击(对象发送方,事件参数e)
{
//调用异步运行的方法。
字符串结果=等待WaitAsynchronouslyAsync();
//调用同步运行的方法。
//string result=wait WaitSynchronously();
//显示结果。
textBox1.Text+=结果;
}
//以下方法异步运行。UI线程不可用
//在延迟期间被阻塞。您可以移动或调整Form1窗口的大小
//正在运行任务。延迟。
公共异步任务WaitAsynchronouslyAsync()
{
等待任务。延迟(10000);
返回“完成”;
}
//以下方法同步运行,尽管使用了async。
//线程处于休眠状态时,无法移动或调整Form1窗口的大小
//正在运行,因为UI线程被阻止。
公共异步任务WaitSynchronously()
{
//添加System.Threading的using指令。
睡眠(10000);
返回“完成”;
}

老实说,我仍然认为最好的解释是维基百科上关于未来和承诺的解释:

基本思想是,您有一个单独的线程池,异步执行任务。使用它的时候。但是,对象确实承诺它将在某个时间执行操作,并在您请求时提供结果。这意味着,当您请求结果且尚未完成时,它将被阻塞,否则将在线程池中执行

从那里,您可以优化事情:一些操作可以异步实现,您可以通过将后续请求批处理在一起和/或重新排序来优化诸如文件IO和网络通信之类的事情。我不确定这是否已经在微软的任务框架中,但如果不是,这将是我要添加的第一件事

实际上,您可以在C#4.0中实现类似于收益率的未来模式。如果你想知道它到底是如何工作的,我可以推荐这个链接,它做得很好:。然而,如果你开始自己玩弄它,你会发现如果你想做所有很酷的事情,你真的需要语言支持——这正是微软所做的

据我所知,async和Wait所做的主要事情之一就是使代码易于编写和阅读

它们使异步代码易于编写和读取,是的

执行长持续时间逻辑是否与生成后台线程相同

一点也不

//我不明白为什么这个方法必须标记为“async”

async
关键字启用
wait
关键字。因此,任何使用
wait
的方法都必须标记为
async

//从DoSomethingAsync()方法睡眠5秒后到达此行。难道不应该立即联系到它吗

否,因为默认情况下,
async
方法不会在另一个线程上运行

//这是在后台线程上执行的吗

没有



你会发现我的建议很有帮助。同样非常好(特别是在这一部分),而且
async
团队提出了一个非常好的解决方案。

当使用
async
wait
时,编译器会在后台生成一个状态机

下面是一个例子,我希望我能解释一些正在进行的高层细节:

public async Task MyMethodAsync()
{
    Task<int> longRunningTask = LongRunningOperationAsync();
    // independent work which doesn't need the result of LongRunningOperationAsync can be done here

    //and now we call await on the task 
    int result = await longRunningTask;
    //use the result 
    Console.WriteLine(result);
}

public async Task<int> LongRunningOperationAsync() // assume we return an int from this long running operation 
{
    await Task.Delay(1000); // 1 second delay
    return 1;
}
公共异步任务MyMethodAsync() { Task longRunningTask=LongRunningOperationAsync(); //不需要LongRunningOperationAsync结果的独立工作可以在这里完成 //现在我们呼吁等待这项任务 int result=等待长时间运行任务; //使用结果 控制台写入线(结果); } 公共异步任务LongRunningOperationAsync()//假定此长时间运行的操作返回int { 等待任务。延迟(1000);//1秒延迟 返回1; } 好的,那么这里发生了什么:

  • Task longRunningTask=LongRunningOperationAsync()开始执行
    LongRunningOperation

  • public async Task MyMethodAsync()
    {
        Task<int> longRunningTask = LongRunningOperationAsync();
        // independent work which doesn't need the result of LongRunningOperationAsync can be done here
    
        //and now we call await on the task 
        int result = await longRunningTask;
        //use the result 
        Console.WriteLine(result);
    }
    
    public async Task<int> LongRunningOperationAsync() // assume we return an int from this long running operation 
    {
        await Task.Delay(1000); // 1 second delay
        return 1;
    }
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace TestingAsync
    {
        class Program
        {
            static void Main(string[] args)
            {
                TestLoops();
                Console.Read();
            }
    
            private static async void TestLoops()
            {
                for (int i = 0; i < 100; i++)
                {
                    await TestAsync(i);
                }
            }
    
            private static Task TestAsync(int i)
            {
                return Task.Run(() => TaskToDo(i));
            }
    
            private async static void TaskToDo(int i)
            {
                await Task.Delay(10);
                Console.WriteLine(i);
            }
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            TestAsyncAwaitMethods();
            Console.WriteLine("Press any key to exit...");
            Console.ReadLine();
        }
    
        public async static void TestAsyncAwaitMethods()
        {
            await LongRunningMethod();
        }
    
        public static async Task<int> LongRunningMethod()
        {
            Console.WriteLine("Starting Long Running method...");
            await Task.Delay(5000);
            Console.WriteLine("End Long Running method...");
            return 1;
        }
    }
    
    Console.WriteLine(DateTime.Now);
    
    // This block takes 1 second to run because all
    // 5 tasks are running simultaneously
    {
        var a = Task.Delay(1000);
        var b = Task.Delay(1000);
        var c = Task.Delay(1000);
        var d = Task.Delay(1000);
        var e = Task.Delay(1000);
    
        await a;
        await b;
        await c;
        await d;
        await e;
    }
    
    Console.WriteLine(DateTime.Now);
    
    // This block takes 5 seconds to run because each "await"
    // pauses the code until the task finishes
    {
        await Task.Delay(1000);
        await Task.Delay(1000);
        await Task.Delay(1000);
        await Task.Delay(1000);
        await Task.Delay(1000);
    }
    Console.WriteLine(DateTime.Now);
    
    5/24/2017 2:22:50 PM
    5/24/2017 2:22:51 PM (First block took 1 second)
    5/24/2017 2:22:56 PM (Second block took 5 seconds)
    
    await a; //Same as the line below
    await a.ConfigureAwait(true);
    
    await a.ConfigureAwait(false);
    
    // Starts counting to a large number and then immediately displays message "I'm counting...". 
    // Then it waits for task to finish and displays "finished, press any key".
    static void asyncTest ()
    {
        Console.WriteLine("Started asyncTest()");
        Task<long> task = asyncTest_count();
        Console.WriteLine("Started counting, please wait...");
        task.Wait(); // if you comment this line you will see that message "Finished counting" will be displayed before we actually finished counting.
        //Console.WriteLine("Finished counting to " + task.Result.ToString()); // using task.Result seems to also call task.Wait().
        Console.WriteLine("Finished counting.");
        Console.WriteLine("Press any key to exit program.");
        Console.ReadLine();
    }
    
    static async Task<long> asyncTest_count()
    {
        long k = 0;
        Console.WriteLine("Started asyncTest_count()");
        await Task.Run(() =>
        {
            long countTo = 100000000;
            int prevPercentDone = -1;
            for (long i = 0; i <= countTo; i++)
            {
                int percentDone = (int)(100 * (i / (double)countTo));
                if (percentDone != prevPercentDone)
                {
                    prevPercentDone = percentDone;
                    Console.Write(percentDone.ToString() + "% ");
                }
    
                k = i;
            }
        });
        Console.WriteLine("");
        Console.WriteLine("Finished asyncTest_count()");
        return k;
    }
    
    using System;
    using System.Threading.Tasks;
    
    public class Program
    {
        public static void Main()
        {               
            var a = MyMethodAsync(); //Task started for Execution and immediately goes to Line 19 of the code. Cursor will come back as soon as await operator is met       
            Console.WriteLine("Cursor Moved to Next Line Without Waiting for MyMethodAsync() completion");
            Console.WriteLine("Now Waiting for Task to be Finished");       
            Task.WaitAll(a); //Now Waiting      
            Console.WriteLine("Exiting CommandLine");       
        }
    
        public static async Task MyMethodAsync()
        {
            Task<int> longRunningTask = LongRunningOperation();
            // independent work which doesn't need the result of LongRunningOperationAsync can be done here
            Console.WriteLine("Independent Works of now executes in MyMethodAsync()");
            //and now we call await on the task 
            int result = await longRunningTask;
            //use the result 
            Console.WriteLine("Result of LongRunningOperation() is " + result);
        }
    
        public static async Task<int> LongRunningOperation() // assume we return an int from this long running operation 
        {
            Console.WriteLine("LongRunningOperation() Started");
            await Task.Delay(2000); // 2 second delay
            Console.WriteLine("LongRunningOperation() Finished after 2 Seconds");
            return 1;
        }   
    
    }
    
    public static void Main(string[] args)
    {
        string result = DownloadContentAsync().Result;
        Console.ReadKey();
    }
    
    // You use the async keyword to mark a method for asynchronous operations.
    // The "async" modifier simply starts synchronously the current thread. 
    // What it does is enable the method to be split into multiple pieces.
    // The boundaries of these pieces are marked with the await keyword.
    public static async Task<string> DownloadContentAsync()// By convention, the method name ends with "Async
    {
        using (HttpClient client = new HttpClient())
        {
            // When you use the await keyword, the compiler generates the code that checks if the asynchronous operation is finished.
            // If it is already finished, the method continues to run synchronously.
            // If not completed, the state machine will connect a continuation method that must be executed WHEN the Task is completed.
    
    
            // Http request example. 
            // (In this example I can set the milliseconds after "sleep=")
            String result = await client.GetStringAsync("http://httpstat.us/200?sleep=1000");
    
            Console.WriteLine(result);
    
            // After completing the result response, the state machine will continue to synchronously execute the other processes.
    
    
            return result;
        }
    }
    
    Device.BeginInvokeOnMainThread(async () => { await AnyAwaitableMethod(); });
    
    // Notice that we do not await the following call, 
    // as that would tie it to the foreground thread.
    try
    {
    Task.Run(async () => { await AnyAwaitableMethod(); });
    }
    catch
    {}
    
    namespace EmailBillingRates
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
                lblProcessing.Text = "";
            }
    
            private async void btnReadExcel_Click(object sender, EventArgs e)
            {
                string filename = OpenFileDialog();
    
                Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
                Microsoft.Office.Interop.Excel.Workbook xlWorkbook = xlApp.Workbooks.Open(filename);
                Microsoft.Office.Interop.Excel._Worksheet xlWorksheet = xlWorkbook.Sheets[1];
                Microsoft.Office.Interop.Excel.Range xlRange = xlWorksheet.UsedRange;
                try
                {
                    Task<int> longRunningTask = BindGrid(xlRange);
                    int result = await longRunningTask;
    
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message.ToString());
                }
                finally
                {
                    //cleanup  
                   // GC.Collect();
                    //GC.WaitForPendingFinalizers();
    
                    //rule of thumb for releasing com objects:  
                    //  never use two dots, all COM objects must be referenced and released individually  
                    //  ex: [somthing].[something].[something] is bad  
    
                    //release com objects to fully kill excel process from running in the background  
                    Marshal.ReleaseComObject(xlRange);
                    Marshal.ReleaseComObject(xlWorksheet);
    
                    //close and release  
                    xlWorkbook.Close();
                    Marshal.ReleaseComObject(xlWorkbook);
    
                    //quit and release  
                    xlApp.Quit();
                    Marshal.ReleaseComObject(xlApp);
                }
    
            }
    
            private void btnSendEmail_Click(object sender, EventArgs e)
            {
    
            }
    
            private string OpenFileDialog()
            {
                string filename = "";
                OpenFileDialog fdlg = new OpenFileDialog();
                fdlg.Title = "Excel File Dialog";
                fdlg.InitialDirectory = @"c:\";
                fdlg.Filter = "All files (*.*)|*.*|All files (*.*)|*.*";
                fdlg.FilterIndex = 2;
                fdlg.RestoreDirectory = true;
                if (fdlg.ShowDialog() == DialogResult.OK)
                {
                    filename = fdlg.FileName;
                }
                return filename;
            }
    
            private async Task<int> BindGrid(Microsoft.Office.Interop.Excel.Range xlRange)
            {
                lblProcessing.Text = "Processing File.. Please wait";
                int rowCount = xlRange.Rows.Count;
                int colCount = xlRange.Columns.Count;
    
                // dt.Column = colCount;  
                dataGridView1.ColumnCount = colCount;
                dataGridView1.RowCount = rowCount;
    
                for (int i = 1; i <= rowCount; i++)
                {
                    for (int j = 1; j <= colCount; j++)
                    {
                        //write the value to the Grid  
                        if (xlRange.Cells[i, j] != null && xlRange.Cells[i, j].Value2 != null)
                        {
                             await Task.Delay(1);
                             dataGridView1.Rows[i - 1].Cells[j - 1].Value =  xlRange.Cells[i, j].Value2.ToString();
                        }
    
                    }
                }
                lblProcessing.Text = "";
                return 0;
            }
        }
    
        internal class async
        {
        }
    }
    
    using System;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace AsyncAwaitDemo
    {
        class Program
        {
            public static async void AsynchronousOperation()
            {
                Console.WriteLine("Inside AsynchronousOperation Before AsyncMethod, Thread Id: " + Thread.CurrentThread.ManagedThreadId);
                //Task<int> _task = AsyncMethod();
                int count = await AsyncMethod();
    
                Console.WriteLine("Inside AsynchronousOperation After AsyncMethod Before Await, Thread Id: " + Thread.CurrentThread.ManagedThreadId);
    
                //int count = await _task;
    
                Console.WriteLine("Inside AsynchronousOperation After AsyncMethod After Await Before DependentMethod, Thread Id: " + Thread.CurrentThread.ManagedThreadId);
    
                DependentMethod(count);
    
                Console.WriteLine("Inside AsynchronousOperation After AsyncMethod After Await After DependentMethod, Thread Id: " + Thread.CurrentThread.ManagedThreadId);
            }
    
            public static async Task<int> AsyncMethod()
            {
                Console.WriteLine("Inside AsyncMethod, Thread Id: " + Thread.CurrentThread.ManagedThreadId);
                int count = 0;
    
                await Task.Run(() =>
                {
                    Console.WriteLine("Executing a long running task which takes 10 seconds to complete, Thread Id: " + Thread.CurrentThread.ManagedThreadId);
                    Thread.Sleep(20000);
                    count = 10;
                });
    
                Console.WriteLine("Completed AsyncMethod, Thread Id: " + Thread.CurrentThread.ManagedThreadId);
    
                return count;
            }       
    
            public static void DependentMethod(int count)
            {
                Console.WriteLine("Inside DependentMethod, Thread Id: " + Thread.CurrentThread.ManagedThreadId + ". Total count is " + count);
            }
    
            static void Main(string[] args)
            {
                Console.WriteLine("Started Main method, Thread Id: " + Thread.CurrentThread.ManagedThreadId);
    
                AsynchronousOperation();
    
                Console.WriteLine("Completed Main method, Thread Id: " + Thread.CurrentThread.ManagedThreadId);
    
                Console.ReadKey();
            }
    
        }
    }
    
    internal static int Method(int arg0, int arg1)
            {
                int result = arg0 + arg1;
                IO(); // Do some long running IO.
                return result;
            }
    
    internal static Task<int> MethodTask(int arg0, int arg1)
        {
            Task<int> task = new Task<int>(() => Method(arg0, arg1));
            task.Start(); // Hot task (started task) should always be returned.
            return task;
        }
    
    internal static async Task<int> MethodAsync(int arg0, int arg1)
        {
            int result = await HelperMethods.MethodTask(arg0, arg1);
            return result;
        }
    
    var myContract = query.Where(c => c.ContractID == _contractID).First();
    
    var myContract = await query.Where(c => c.ContractID == _contractID).FirstAsync();
    
        public static void DoSomeWork()
        {
            var task = Task.Run(() =>
            {
                // [RUNS ON WORKER THREAD]
    
                // IS NOT bubbling up due to the different threads
                throw new Exception();
                Thread.Sleep(2000);
    
                return "Hello";
            });
    
            // This is the callback
            task.ContinueWith((t) => {
                // -> Exception is swallowed silently
                Console.WriteLine("Completed");
    
                // [RUNS ON WORKER THREAD]
            });
        }
    
        public async static void DoSomeWork()
        {
            var result = await Task.Run(() =>
            {
                // [RUNS ON WORKER THREAD]
    
                // IS bubbling up
                throw new Exception();
                Thread.Sleep(2000);
    
                return "Hello";
            });
    
            // every thing below is a callback 
            // (including the calling methods)
    
            Console.WriteLine("Completed");
    
        }
    
        public static long DoTask()
        {
            stopWatch.Reset();
            stopWatch.Start();
    
            // [RUNS ON MAIN THREAD]
            var task = Task.Run(() => {
                Thread.Sleep(2000);
                // [RUNS ON WORKER THREAD]
            });
            // goes directly further
            // WITHOUT waiting until the task is finished
    
            // [RUNS ON MAIN THREAD]
    
            stopWatch.Stop();
            // 50 milliseconds
            return stopWatch.ElapsedMilliseconds;
        }
    
        public async static Task<long> DoAwaitTask()
        {
            stopWatch.Reset();
            stopWatch.Start();
    
            // [RUNS ON MAIN THREAD]
    
            await Task.Run(() => {
                Thread.Sleep(2000);
                // [RUNS ON WORKER THREAD]
            });
            // Waits until task is finished
    
            // [RUNS ON MAIN THREAD]
    
            stopWatch.Stop();
            // 2050 milliseconds
            return stopWatch.ElapsedMilliseconds;
        }
    
        public static Stopwatch stopWatch { get; } = new Stopwatch();
    
        static void Main(string[] args)
        {
            Console.WriteLine("DoAwaitTask: " + DoAwaitTask().Result + " ms");
            // 2050 (2000 more because of the await)
            Console.WriteLine("DoTask: " + DoTask() + " ms");
            // 50
            Console.ReadKey();
        }
    
    async void DoSomething(){ . . .
    
        //ASYNCHRONOUS
        //this is called using the await keyword every 5 seconds from a polling timer or something.
    
        async Task CheckWeather()
        {
            var weather = await GetWeather();
            //do something with the weather now you have it
        }
    
        async Task<WeatherResult> GetWeather()
        {
    
            var weatherJson = await CallToNetworkAddressToGetWeather();
            return deserializeJson<weatherJson>(weatherJson);
        }
    
        //SYNCHRONOUS
        //This method is called whenever the screen is pressed
        void ScreenPressed()
        {
            DrawSketchOnScreen();
        }
    
    // awaiting this will return a string.
    // calling this without await (synchronously) will result in a Task<string> object.
    async Task<string> FetchHelloWorld() {..
    
    async string FetchHelloWorld() {..