关闭与后台工作程序WorkRunCompleted在不同线程上创建的wpf窗口 [英] Closing a wpf window created on a different thread from the background worker WorkRunCompleted
问题描述
您好,此处
这是摘要
在C#中的wpf应用程序中,我花了很长时间来更新远程数据库.为此,我创建了一个后台工作者.但是我想在数据库更新过程中打开一个窗口并运行一个进度条.我在将进度栏设置为Indeterminate的主窗口上实现此目标的所有尝试均失败了,因为直到我的后台工作线程完成后,对进度栏的摆动"效果才开始在我的主窗口上运行
任何有帮助的人和本文这里我设法在另一个线程中打开一个新窗口,并运行后台工作程序,并正确地使进度栏旋转",并且后台工作已完成.但是,我的新问题是
背景工作完成后,如何关闭进度栏窗口(称为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和类是这个;
<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;
}
在进度页中执行背景
如果您需要传递(并返回)一个对象,请在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();
}
}
}
Hi there is a follow up to another question here
Here is the summary
In a wpf application in c# I had a long process of updating a remote database. to do this I created a background worker. However I wanted to have a window open and a progressbar run during the database update routine. All my attempts to achieve this on my main window with a progressbar set to Indeterminate failed as the "swishing" effect on my progressbar did not start to run on my main window till after my background worker thread had finished
Any with help and this article here I managed to open a new window in a different thread and run the background worker and have the progressbar "swish" properly and the background work run to completion. HOWEVER, my new question is
How do I close my progressbar window (called progressDialog) once my background work is finished?
Please bear in mind that I am quite new to this and code examples would be greatly apprieciated and I THINK, but I am not certain I am going to want to close the progressbar window from the background worker RunWorkerCompleted area of code
here is my code
I set up the background worker as
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);
}
}
I run the event on a button click event as;
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);
}
}
My progressbar form progressDialog xaml and class are this;
<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;
}
My background worker completed code is
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;
}
Do the Background in the progress page
If you need to pass (and return) an object then do so in the 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();
}
}
}
这篇关于关闭与后台工作程序WorkRunCompleted在不同线程上创建的wpf窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!