我有一个 C# WindowsForm 应用程序,它读取 CSV 文件并过滤掉文件中出现的任何“错误”。然后,该应用程序允许用户通过特定过滤器(即郊区)过滤数据。一旦过滤了错误,就会显示该表单。但是,这需要几秒钟。在此期间,我想显示启动/加载屏幕以显示应用程序正在加载。
我已经创建了一个显示启动画面的线程,但是,下面显示的代码会引发以下错误。
System.ComponentModel.InvalidAsynchronousStateException: '调用该方法时发生错误。目标线程不再存在。'
private void UpdateLabel(object sender, ElapsedEventArgs e)
{
if (Thread.CurrentThread.IsAlive)
{
if (lblLoading.InvokeRequired)
{
if (count == 0)
{
lblLoading.Invoke(new Action(() => lblLoading.Text = "Loading."));
count++;
}
else if (count == 1)
{
lblLoading.Invoke(new Action(() => lblLoading.Text = "Loading.."));
count++;
}
else if (count == 2)
{
lblLoading.Invoke(new Action(() => lblLoading.Text = "Loading..."));
count++;
}
else
{
lblLoading.Invoke(new Action(() => lblLoading.Text = "Loading"));
count = 0;
}
}
else
{
if (count == 0)
{
lblLoading.Text = "Loading.";
count++;
}
else if (count == 1)
{
lblLoading.Text = "Loading..";
count++;
}
else if (count == 2)
{
lblLoading.Text = "Loading...";
count++;
}
else
{
lblLoading.Text = "Loading";
count = 0;
}
}
}
}
甚至在更新标签之前,启动画面也会在错误检查之前关闭。
谢谢,nozzy
在 Winform 代码中使用 backgroundWorker 会是这样的:
在按钮上单击:
//SHOW YOUR SCREEN
backgrounWorker.Runasync();
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// here you can call :
backgroundWorker1_ProgressChanged(0,"abc");
backgroundWorker1_ProgressChanged(2,"abc");
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{// show your progress here
if(e.progresspercentage==0){
listBox3.Items.Insert(0, e.UserState.ToString());
listBox3.Update();}
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//remove splash screen here
}
这是@Sir Rufo 提到的 IProgress 的基本示例。
使用 .NET Core 7 编码 没有异常处理,但您需要添加它,尤其是在处理文件时。
执行工作的模型,在本例中 Task.Delay 将被您的工作替换。
public class Operations
{
public static async Task PerformWork(IProgress<int> progress, CancellationToken cancellationToken)
{
for (int index = 0; index <= 100; index++)
{
// Simulate an async call that takes some time to complete
await Task.Delay(100, cancellationToken);
if (cancellationToken.IsCancellationRequested)
{
cancellationToken.ThrowIfCancellationRequested();
}
progress?.Report(index);
}
}
}
MainForm 在 Shown 事件中显示二级窗体,随意更改为 Load 事件。
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
Shown += MainForm_Shown;
}
private void MainForm_Shown(object sender, EventArgs e)
{
SplashForm splashForm = new();
try
{
if (splashForm.ShowDialog() == DialogResult.OK)
{
// work completed
}
else
{
// user cancelled
}
}
finally
{
splashForm.Dispose();
}
}
}
Splash 表单,注意 ReportProgress 更新一个进度条,也可以是一个标签。此外,还有一个您可能不想要的取消按钮。
public partial class SplashForm : Form
{
private readonly CancellationTokenSource
_cancellationTokenSource = new();
public SplashForm()
{
InitializeComponent();
Shown += SplashForm_Shown;
}
private async void SplashForm_Shown(object sender, EventArgs e)
{
var cancelled = false;
var progressIndicator = new Progress<int>(ReportProgress);
try
{
await Operations.PerformWork(
progressIndicator,
_cancellationTokenSource.Token);
// indicates success to main form and closes this form
DialogResult = DialogResult.OK;
}
catch (OperationCanceledException ex)
{
cancelled = true;
}
if (cancelled)
{
MessageBox.Show("Cancelled");
// indicates user cancelled to main form and closes this form
DialogResult = DialogResult.Cancel;
}
}
/// <summary>
/// Update progress bar from Operations.
/// </summary>
/// <param name="value"></param>
private void ReportProgress(int value)
{
progressBar1.Increment(1);
}
private void CancelOperationButton_Click(object sender, EventArgs e)
{
_cancellationTokenSource.Cancel();
}
}