【问题标题】:Closing a wpf window created on a different thread from the background worker WorkRunCompleted关闭在与后台工作程序 WorkRunCompleted 不同的线程上创建的 wpf 窗口
【发布时间】:2023-03-28 07:24:01
【问题描述】:

您好,有另一个问题here

这里是总结

在 c# 中的 wpf 应用程序中,我有一个更新远程数据库的漫长过程。为此,我创建了一个后台工作人员。但是,我希望在数据库更新例程期间打开一个窗口并运行一个进度条。我在主窗口上将进度条设置为 Indeterminate 的所有尝试都失败了,因为我的进度条上的“嗖嗖”效果直到我的后台工作线程完成后才开始在我的主窗口上运行

任何有帮助的人和这篇文章here 我设法在不同的线程中打开一个新窗口并运行后台工作程序,并使进度条正确“摆动”,后台工作运行完成。但是,我的新问题是

后台工作完成后如何关闭进度条窗口(称为 progressDialog)?

请记住,我对此很陌生,我会非常喜欢代码示例并且我认为,但我不确定我是否要从后台工作人员 RunWorkerCompleted 代码区域关闭进度条窗口

这是我的代码

我将后台工作人员设置为

  public partial class MainWindow : Window
{
    //Declare background workers
    BackgroundWorker bwLoadCSV = new BackgroundWorker();


    //Declare class variables
    // some stuff

    public MainWindow()
    {
        InitializeComponent();
        //assign events to backgroundworkers
        bwLoadCSV.WorkerReportsProgress = true;
        bwLoadCSV.WorkerSupportsCancellation = true;
        bwLoadCSV.DoWork += new DoWorkEventHandler(bwLoadCSV_DoWork);
        bwLoadCSV.ProgressChanged += new ProgressChangedEventHandler(bwLoadCSV_ProgressChanged);
        bwLoadCSV.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bwLoadCSV_RunWorkerCompleted);
      }
  }

我在按钮单击事件上运行该事件;

private void CSV_Load_Click(object sender, RoutedEventArgs e)
    ///Function to read csv into datagrid
    ///
    {
        //Turn Cursor to wait
        System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.WaitCursor;
        Thread backgroundThread = new Thread(
    new ThreadStart(() =>
    {
        ProgressDialog progressDialog = new ProgressDialog();
        progressDialog.tbEvent.Text = "Loading CSV Data....";
        progressDialog.progressBar1.IsIndeterminate = true;
        progressDialog.ShowDialog();
    }

));
        backgroundThread.SetApartmentState(ApartmentState.STA);
        backgroundThread.Start();

        //Test connection to sql server
        if (CHHoursDataProvider.IsDatabaseOnline() == false)
        {
            System.Windows.Forms.MessageBox.Show("Can not establish contact with sql server" + "\n" + "Contact IT", "Connection Error");
            //Set UI picture
            return;
        }
        //Set a control to update the user here
        tbLoadDgStat.Visibility = Visibility.Visible;

        //tbLoadDgStat.Text = "Getting data templete from Database...";
        string FilePath = txFilePath.Text;
        if (bwLoadCSV.IsBusy != true)
        {
            //load the context object with parameters for Background worker
            bwCSVLoadContext Context = new bwCSVLoadContext();
            Context.Site = cBChSite.Text;
            Context.FilePath = txFilePath.Text;
            Context.FileName = fileTest;
            Context.Wageyear = cbWageYear.Text;
            Context.Startdate = ((DateTime)dpStartDate.SelectedDate);
            Context.Enddate = ((DateTime)dpEndDate.SelectedDate);

            bwLoadCSV.RunWorkerAsync(Context);                
         }
    }

我的进度条表单progressDialog xaml和class是这样的;

<Window x:Class="Test_Read_CSV.ProgressDialog"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Progress Dialog" Height="115" Width="306" Name="ProgressPopup">
<Grid>
    <ProgressBar Height="31" HorizontalAlignment="Left" Margin="12,33,0,0" Name="progressBar1" VerticalAlignment="Top" Width="250" x:FieldModifier="public" />
    <TextBox Height="23" HorizontalAlignment="Left" Margin="7,4,0,0" Name="tbEvent" VerticalAlignment="Top" Width="254" IsReadOnly="True" IsEnabled="False" x:FieldModifier="public" />
</Grid>

class is
 public partial class ProgressDialog : Window
{
    public ProgressDialog()
    {
        WindowStartupLocation = WindowStartupLocation.CenterScreen;
        InitializeComponent();
        progressBar1.IsIndeterminate = true;

    }

我的后台工作人员完成的代码是

  private void bwLoadCSV_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        bwCSVLoadContext Context = e.Result as bwCSVLoadContext;
        Thread.Sleep(5000);
        if ((e.Cancelled == true))
        {

            this.tbLoadDgStat.Text = "Canceled!";
            System.Threading.Thread.Sleep(1000);

            System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Default;
            tbLoadDgStat.Visibility = Visibility.Hidden;
        }

        else if (!(e.Error == null))
        {
            //this.tbProgress.Text = ("Error: " + e.Error.Message);

        }

        else
        {
            if (Context.LoadResult == true)
            {
                this.dgCSVData.DataContext = oTable.DefaultView;
                btUpload.IsEnabled = true;
            }

            **//close the progressbar window some how here!!!**


            //On the main window
            this.tbLoadDgStat.Text = "Complete";
            progressBar1.Value = 100;


            System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Default;
            tbLoadDgStat.Visibility = Visibility.Hidden;
        }



        System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Default;

    }

【问题讨论】:

  • 如果您使用的是 .NET 4.5,使用 Async 和 Await 以及带有进度/取消令牌的任务会容易得多。这些链接应该有助于加快速度。我发现它们也更容易避免交叉线程问题。 [1]:msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx [2]:blogs.msdn.com/b/dotnet/archive/2012/06/06/…
  • 不幸的是;它是.Net 4.0,但我会看看谢谢
  • @HockeyJ 你认为异步 CTP 适合我吗?
  • 我在生产环境中使用了这两种方法,发现 Async 和 Tasks 的组合比旧式线程和后台工作人员更容易使用。还没有找到回归旧方式的案例。

标签: c# wpf multithreading backgroundworker


【解决方案1】:

在进度页面做背景
如果您需要传递(并返回)一个对象,请在 Progress ctor 中这样做

private void click(object sender, RoutedEventArgs e)
{
    Progress progressDialog = new Progress();
    progressDialog.Show();
    if (progressDialog != null) progressDialog = null;
}

namespace BackGroundWorkerShowDialog
{
    /// <summary>
    /// Interaction logic for Progress.xaml
    /// </summary>
    public partial class Progress : Window
    {
        BackgroundWorker bwLoadCSV = new BackgroundWorker();
        public Progress()
        {
            InitializeComponent();
            //assign events to backgroundworkers
            bwLoadCSV.WorkerReportsProgress = true;
            bwLoadCSV.WorkerSupportsCancellation = true;
            bwLoadCSV.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
            bwLoadCSV.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
            bwLoadCSV.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
            if (bwLoadCSV.IsBusy != true)
            {
                // Start the asynchronous operation.
                bwLoadCSV.RunWorkerAsync();
            }

        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
            for (int i = 1; i <= 10; i++)
            {
                if (worker.CancellationPending == true)
                {
                    e.Cancel = true;
                    break;
                }
                else
                {
                    // Perform a time consuming operation and report progress.
                    System.Threading.Thread.Sleep(500);
                    worker.ReportProgress(i * 10);
                }
            }
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {

            if (e.Cancelled == true)
            {
                //resultLabel.Text = "Canceled!";
            }
            else if (e.Error != null)
            {
                //resultLabel.Text = "Error: " + e.Error.Message;
            }
            else
            {
                //resultLabel.Text = "Done: " + e.Error.Message;
            }
            this.Close();
        }

        private void backgroundWorker1_ProgressChanged(object sender,
            ProgressChangedEventArgs e)
        {
            this.tbProgress.Text = e.ProgressPercentage.ToString();
        }
    }

}

【讨论】:

  • 嗨 @Blam 不幸的是,我收到异常“错误 1,名称 'progressDialog' 在当前上下文中不存在”当它被放入 bwLoadCSV_RunworkerCompleted 时
  • 我在 ThreadStart 上进行了测试,发现错误。一旦你有一个接受的答案,我会删除。
  • 嗨@Blam,我解决了这个问题,正如你所说,我只需要在回电的地方玩弄就可以解决这个问题
猜你喜欢
  • 2019-05-06
  • 2011-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-30
  • 1970-01-01
  • 2013-06-08
  • 2012-04-22
相关资源
最近更新 更多