I was able resolve the issue with the input form Stephen Cleary. Please see update 3.
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);
}
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);
}
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.
Update 3:
Here is the final code
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();
}
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…