是否可以在没有 BackgroundWorker 的情况下使 WinForms 响应?
Is it possible to make WinForms responsive without BackgroundWorker?
我有一个在 C# 中使用 WinForms 制作的程序,它使用了另一个开发人员提供的 API,并且它在主线程中必须是 运行(因为它正在使用 WM_Messages ,但也可能有其他原因)-所以我不能使用 BackgroundWorker。我的程序 运行s 至少 15 分钟 API。因此,当我 运行 它并单击表单时,它会冻结并崩溃,因为它没有响应。
在使用 API?
时,我该怎么做才能使表单响应并且不触发 Windows 警报“应用程序未响应”
这是我运行循环给定文件夹中所有文件名的代码:
fApi.ApiSetDates(DateTime.MinValue, DateTime.MinValue, invoiceIssueDate.Year, invoiceIssueDate.Month);
try
{
if (fApi.ImportFakturFromXML(fileName) != 0)
{
throw new Exception(fApi.GetLastError());
}
File.Delete(fileName);
}
catch (Exception x)
{
MessageBox.Show(x.ToString());
}
这是一个非设计人员生成的代码,用于一个小 Windows 表单,当其单独的按钮时,该表单在循环中执行许多长 运行、UI 线程阻塞操作被点击。与我最初在评论中建议的 Timer 相比,此代码更具可读性和可维护性,并且比 D.Kastier 在他的回答的评论中建议的代码更直接。
namespace LongRunningLoop
{
public partial class Form1 : Form
{
private bool m_Closed = false;
public Form1()
{
InitializeComponent(); // set up button1
}
// async void event handler. Usually async void
// is a no-no, but here we really do want to fire and forget.
// We prevent nasty things from happening by disabling the UI
// before starting the main work and exiting if we detect
// that the form has been closed.
private async void button1_Click(object sender, EventArgs e)
{
// Disable the UI so there's no reentrancy during the Task.Delay()
button1.Enabled = false;
for (int i = 0; i < 60; i++)
{
if (m_Closed)
{
// Don't keep doing work if the user has closed the form
break;
}
Thread.Sleep(5000); // A long-running, blocking call (sleep thread for 5 seconds)
await Task.Delay(100); // Yield to allow other events to be processed
}
// Re-enable the UI
button1.Enabled = true;
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
// Set a flag to signal the loop to exit
m_Closed = true;
}
}
}
我有一个在 C# 中使用 WinForms 制作的程序,它使用了另一个开发人员提供的 API,并且它在主线程中必须是 运行(因为它正在使用 WM_Messages ,但也可能有其他原因)-所以我不能使用 BackgroundWorker。我的程序 运行s 至少 15 分钟 API。因此,当我 运行 它并单击表单时,它会冻结并崩溃,因为它没有响应。 在使用 API?
时,我该怎么做才能使表单响应并且不触发 Windows 警报“应用程序未响应”这是我运行循环给定文件夹中所有文件名的代码:
fApi.ApiSetDates(DateTime.MinValue, DateTime.MinValue, invoiceIssueDate.Year, invoiceIssueDate.Month);
try
{
if (fApi.ImportFakturFromXML(fileName) != 0)
{
throw new Exception(fApi.GetLastError());
}
File.Delete(fileName);
}
catch (Exception x)
{
MessageBox.Show(x.ToString());
}
这是一个非设计人员生成的代码,用于一个小 Windows 表单,当其单独的按钮时,该表单在循环中执行许多长 运行、UI 线程阻塞操作被点击。与我最初在评论中建议的 Timer 相比,此代码更具可读性和可维护性,并且比 D.Kastier 在他的回答的评论中建议的代码更直接。
namespace LongRunningLoop
{
public partial class Form1 : Form
{
private bool m_Closed = false;
public Form1()
{
InitializeComponent(); // set up button1
}
// async void event handler. Usually async void
// is a no-no, but here we really do want to fire and forget.
// We prevent nasty things from happening by disabling the UI
// before starting the main work and exiting if we detect
// that the form has been closed.
private async void button1_Click(object sender, EventArgs e)
{
// Disable the UI so there's no reentrancy during the Task.Delay()
button1.Enabled = false;
for (int i = 0; i < 60; i++)
{
if (m_Closed)
{
// Don't keep doing work if the user has closed the form
break;
}
Thread.Sleep(5000); // A long-running, blocking call (sleep thread for 5 seconds)
await Task.Delay(100); // Yield to allow other events to be processed
}
// Re-enable the UI
button1.Enabled = true;
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
// Set a flag to signal the loop to exit
m_Closed = true;
}
}
}