await, anync

本文深入解析了C#中异步方法如何与UI线程交互,通过对比`Task.Delay`与`Thread.Sleep`的不同行为,阐述了异步方法在UI更新上的优势与限制。详细演示了如何在异步操作完成后更新UI控件,以及异步方法执行与UI事件处理之间的协调。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

public Form1()
        {
            InitializeComponent();
        }

        // The following method runs asynchronously. The UI thread is not
        // blocked during the delay. You can move or resize the Form1 window 
        // while Task.Delay is running.
        public async Task<string> WaitAsynchronouslyAsync()
        {
            await Task.Delay(10000);
            MessageBox.Show("fi");
            return "Finished";
        }

        // The following method runs synchronously, despite the use of async.
        // You cannot move or resize the Form1 window while Thread.Sleep
        // is running because the UI thread is blocked.
        public async Task<string> WaitSynchronously()
        {
            // Add a using directive for System.Threading.
            Thread.Sleep(10000);
            return "Finished";
        }

        private async void button1_Click_1(object sender, EventArgs e)
        {
            string result = string.Empty;
            WaitAsynchronouslyAsync();

            // Call the method that runs asynchronously.
            //result = await WaitAsynchronouslyAsync();
            // Call the method that runs synchronously.
            // result = await WaitSynchronously ();

            // Display the result.
            textBox1.Text += result;
            MessageBox.Show("hi");
        }
上述代码得出至少两点:
1. await WaitAsynchronouslyAsync() 执行时要等待这个调用完成,才会执下后面的代码,但在这个调用没有完成前,其thread是可以被其它代码占用的,表现就是UI仍可以接收其它消息
2. WaitAsynchronouslyAsync()函数执行的线程与UI主线程是同一个,这也是为什么在这个函数中的messagebox可以显示,Thread.sleep可以阻止UI线程接收消息

 

转载于:https://www.cnblogs.com/sdikerdong/p/4398961.html

06-14
### Await 异步编程用法及常见问题 异步编程是现代编程中处理耗时操作(如网络请求、文件读写等)的核心技术之一。`async` 和 `await` 是实现异步编程的一种简洁方式,它们使异步代码的编写和阅读更直观。以下是关于 `await` 的详细用法及常见问题的解答。 #### 1. 基本用法 `await` 关键字用于等待一个异步操作完成,它只能在标记为 `async` 的函数中使用。当执行到 `await` 表达式时,程序会暂停当前函数的执行,直到等待的异步操作完成,然后继续执行后续代码[^1]。 ```javascript async function fetchData() { try { const response = await fetch('https://api.example.com/data'); // 等待网络请求完成 const data = await response.json(); // 等待解析 JSON 完成 console.log(data); } catch (error) { console.error('Error fetching data:', error); } } ``` #### 2. 常见问题及解决方案 ##### 问题 1: `async` 函数中有 `await` 表达式 如果一个函数被标记为 `async`,但其中有任何 `await` 表达式,则该函数会像同步函数一样执行。尽管如此,编译器通常会发出警告以提示开发者这种潜在的误用。 ```javascript async function example() { console.log('This function is async but contains no await.'); } example(); // 输出: This function is async but contains no await. ``` ##### 问题 2: 异步编程是否创建新线程 异步编程本质上并不意味着多线程。虽然某些异步操作可能会在后台线程中运行(例如 I/O 操作),但 `async` 函数本身不会直接启动新线程。实际上,`async` 函数中的代码仍然在调用线程中执行,直到遇到 `await` 表达式才会暂停[^2]。 ```javascript async function example() { console.log('Start'); await new Promise(resolve => setTimeout(resolve, 1000)); // 模拟耗时操作 console.log('End after 1 second'); } example(); console.log('This will execute immediately.'); ``` ##### 问题 3: `await` 后未正确处理返回值或异常 当使用 `Task.WhenAny` 或类似方法时,必须注意 `await` 的对象并不是最终结果,而是另一个 `Task` 对象。因此需要再次 `await` 来获取实际结果或确保异常被抛出[^3]。 ```csharp var task1 = Task.Delay(1000).ContinueWith(t => "Result from Task 1"); var task2 = Task.Delay(2000).ContinueWith(t => "Result from Task 2"); var finishedTask = await Task.WhenAny(task1, task2); // 等待任一任务完成 var result = await finishedTask; // 再次等待以获取实际结果 Console.WriteLine(result); ``` ##### 问题 4: 错误处理 `try-catch` 结构可以捕获由 `await` 表达式引发的异常,从而简化错误处理逻辑。此外,与传统的 `Promise` 链相比,`async/await` 提供了更清晰的错误处理机制[^4]。 ```javascript async function fetchData() { try { const response = await fetch('https://api.example.com/nonexistent'); if (!response.ok) throw new Error('Network response was not ok'); const data = await response.json(); console.log(data); } catch (error) { console.error('Error:', error.message); } } ``` #### 3. 优势与局限性 - **优势**: - 异步代码的结构类似于同步代码,避免了 `Promise` 链接嵌套的问题。 - 使用 `try-catch` 可同时处理同步和异步错误,提升了调试效率。 - **局限性**: - 如果不正确地使用 `await`,可能导致性能问题,例如不必要的阻塞。 - 在某些框架(如 Flutter)中,可能需要额外的方法来处理异步任务的结果[^5]。 ```dart Future<void> fetchData() async { try { final response = await http.get(Uri.parse('https://api.example.com/data')); if (response.statusCode == 200) { print('Data fetched successfully'); } else { throw Exception('Failed to load data'); } } on Exception catch (e) { print('Error: $e'); } } ``` #### 4. 最佳实践 - 总是将 `async` 和 `await` 配对使用,避免在非异步上下文中误用 `await`。 - 在处理多个异步任务时,考虑使用 `Promise.all` 或 `Task.WhenAll` 等方法以提高效率。 - 确保所有可能的异常都被适当捕获并处理。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值