如何在 CSV 被错误检查时显示加载/启动屏幕 - C# WinForms?

问题描述 投票:0回答:2

我有一个 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

c# winforms thread-safety
2个回答
0
投票

在 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
        }

0
投票

这是@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();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.