我能够使用输入表单Stephen Cleary解决此问题.请参阅更新3.
I was able resolve the issue with the input form Stephen Cleary. Please see update 3.
我有一个Windows Forms应用程序,该应用程序带有带有async修饰符的方法.如果在按钮的click事件中调用该方法,则该方法不会阻止UI线程.但是,当我在计时器内部将其作为回调调用时,它将冻结UI.我无法弄清楚我在做什么错.请在下面查看我的代码.这只是一个示例项目,用于演示.
I have a Windows Forms application that has a method with the async modifier. If the method is called inside a button's click event it does not block the UI thread. However, when I call it inside a timer as a callback it freezes the UI. I could not figure out what I am doing wrong here. Please see below my code. This is just a sample project for demonstration purposes.
public Form1() { InitializeComponent(); } private async void formCloseAsync() { shutdown stf = new shutdown(); stf.StartPosition = FormStartPosition.CenterScreen; stf.Show(); var task = Task.Factory.StartNew(processClose); await task; } private void processClose() { Thread.Sleep(5000); Environment.Exit(1); } private void simpleButtonAsync_Click(object sender, EventArgs e) { formCloseAsync(); } private void _simpleButtonTimer_Click(object sender, EventArgs e) { Timer _shutdownTimer = new Timer(delegate { formCloseAsync(); }, null, 5000, Timeout.Infinite); }更新1:谢谢大家的宝贵意见.请在下面查看更新的代码
Update 1: Thanks All for your valuable input. Please see the updated code below
public Form1() { InitializeComponent(); } private Timer _shutdownTimer; private void formCloseAsync() { shutdown stf = new shutdown(); stf.StartPosition = FormStartPosition.CenterScreen; stf.Show(); Task.Run(async ()=> { await Task.Delay(5000); Environment.Exit(1); } ); } private void simpleButtonAsync_Click(object sender, EventArgs e) { formCloseAsync(); } private void _simpleButtonTimer_Click(object sender, EventArgs e) { _shutdownTimer = new Timer(async delegate { formCloseAsync(); }, null, 0, Timeout.Infinite); }但是我仍然有同样的问题.在内部计时器回调中调用shutdown stf时被阻止.主界面还可以.没问题.我只希望从计时器回调创建的shutdown(stf)GUI能够响应.关机GUI带有进度条.
However I still have the same issue. shutdown stf is blocked when called inside timer callback. Main UI is okay. No issue with that. I just want the shutdown(stf) GUI to be responsive when created from timer call back. Shutdown GUI has a progress bar.
更新3:
这是最终代码
public partial class Form1 : Form { readonly shutdown _stf = new shutdown(); public Form1() { InitializeComponent(); } private Timer _shutdownTimer; private async Task formCloseAsync() { try { BeginInvoke(new MethodInvoker(delegate { _stf.StartPosition = FormStartPosition.CenterScreen; _stf.Show(); })); await Task.Run( async () => { await Task.Delay(5000); }); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } finally { Environment.Exit(1); } } private void simpleButtonAsync_Click(object sender, EventArgs e) { formCloseAsync(); } private void _simpleButtonTimer_Click(object sender, EventArgs e) { _shutdownTimer = new Timer(async delegate { formCloseAsync(); }, null, 0, Timeout.Infinite); } private async void Form1_FormClosing(object sender, FormClosingEventArgs e) { e.Cancel = true; await formCloseAsync(); } 推荐答案
但是,当我在计时器中作为回调调用它时,它会冻结UI.
However, when I call it inside a timer as a callback it freezes the UI.
您无法从后台线程访问UI元素(我猜 stf.Show(); 正在显示一个对话框).最简单的解决方法可能是将 System.Threading.Timer 替换为 Windows.Forms.Timer .
You can't access UI elements from background threads (I'm guessing stf.Show(); is showing a dialog). The easiest fix is probably to replace System.Threading.Timer with Windows.Forms.Timer.
其他说明:
- 您不应为此使用 StartNew ;请改用 Task.Run .请参阅我的博客文章 StartNew 是危险的.
- 除了事件处理程序外,您不应将 async void 用于其他任何用途.请参阅我的MSDN文章异步编程的最佳实践.
- You shouldn't use StartNew for that; use Task.Run instead. See my blog post StartNew is dangerous.
- You shouldn't use async void for anything other than event handlers. See my MSDN article Best Practices in Asynchronous Programming.
更多推荐
与线程计时器异步/等待
发布评论