嘿大家,有人能让我知道他们看错了这段代码吗?
在
上抛出“跨线程操作无效”异常_DialogueThread.Start();
但如果我从
中删除“所有者”_progressDialogue = new Progresser{Owner = _owner, StartPosition = FormStartPosition.CenterParent};
不会抛出异常,但会显示progressDialouge,然后立即隐藏。
现在我理解为什么如果我将progressDialouge.Owner设置为在不同线程上创建的父窗体,则会抛出此错误。但为什么剂量表格消失时,我不?我做错了什么?
感谢
class Sampleer : BackgroundWorker
{
private Progresser _progressDialogue;
private Thread _DialogueThread;
private Form _owner;
private bool _SampleSuccess;
public Sampleer(Form owner)
{
_owner = owner;
_progressDialogue = new Progresser{Owner = _owner, StartPosition = FormStartPosition.CenterParent};
_progressDialogue.Closed += ProgressDialogueClosed;
WorkerReportsProgress = true;
WorkerSupportsCancellation = true;
DoWork += Sampleer_DoWork;
RunWorkerCompleted += Sampleer_RunWorkerCompleted;
ProgressChanged += Sampleer_ProgressChanged;
}
private void Sampleer_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//UPDATE STATUS CODE IS HERE
}
void ProgressDialogueClosed(object sender, EventArgs e)
{
CancelAsync();
Dispose();
}
void Sampleer_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//FINISH PROCESS
}
void Sampleer_DoWork(object sender, DoWorkEventArgs e)
{
_DialogueThread = new Thread(_progressDialogue.Show);
_DialogueThread.Start();
//DO LONG PROCESS HERE
}
}
答案 0 :(得分:1)
在您的操作(按钮单击)中,我将创建进度对话框,然后关闭后台工作程序。然后,后台工作程序将报告回ProgressChanged事件中的对话框。
public partial class MainWindow : Window {
private void btnDoSomething_Click(object sender0, RoutedEventArgs e0) {
_progressDialogue = new Progresser{Owner = _owner, StartPosition = FormStartPosition.CenterParent};
_progressDialogue.Closed += ProgressDialogueClosed;
_progressDialogue.Show();
BackgroundWorker worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.DoWork += delegate(object sender, DoWorkEventArgs e) {
DoSomething();
e.Result = result;
};
worker.ProgressChanged += delegate(object sender, ProgressChangedEventArgs e) {
progressDialogue.Update()
};
worker.RunWorkerCompleted += delegate(object sender, RunWorkerCompletedEventArgs e) {
progressDialogue.Close()
};
worker.RunWorkerAsync(new CustomArgs() {
SomeValue = txtValue.Text,
});
}
}
答案 1 :(得分:1)
你的方法有一些错误。让我一个一个地指出它们。
您继承BackgroundWorker
。那样就好。但是你在里面创建了另一个线程(_DialogueThread
)。没有必要。 DoWork()
方法在一个单独的线程中运行。
您在另一个线程中创建/使用/操作UI
元素。现在,永远记住。 Thread
永远不会创建UI
元素。它的另一种方式。 UI
元素会创建Thread
。在您的情况下,Progresser
应该创建新的Thread
或使用BackgroundWorker
来执行您需要的任何后台工作。
`
答案 2 :(得分:0)
是的,decyclone是对的,代码和解决方法中存在许多错误。
您是否正在使用BackgroundWorker类型但订阅自己的事件? 而是覆盖负责在类中引发事件的方法。 例如:不是订阅DoWork,而是覆盖OnDoWork方法。
我已经创建了一个示例应用程序,其中一个Form(执行后台任务时)显示另一个Form(BackgroundWorkUINotification)并在BackgroundWorker线程中启动后台任务。单击表单的CancelButton时,BackgroundWorkUINotification会通知主窗体。
通知主表单时,关闭通知程序并取消后台任务。
以下代码:BackgroundWorkUINotification表格
public partial class BackgroundWorkUINotification : Form
{
public event EventHandler CancelClicked;
public BackgroundWorkUINotification()
{
InitializeComponent();
// call code to animate progress bar..
// probably in another BackgroundWorker that reports progress..
this.cancelButton.Click += HandleCancelButtonOnClick;
}
protected virtual void OnCancelClicked()
{
if (CancelClicked != null)
this.CancelClicked(this, EventArgs.Empty);
}
private void HandleCancelButtonOnClick(Object sender, EventArgs e)
{
this.OnCancelClicked();
}
}
主要表格
public partial class Form1 : Form
{
private BackgroundWorker backgroundWorker;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
this.backgroundWorker = new BackgroundWorker();
this.backgroundWorker.DoWork += HandleBackgroundWorkerOnDoWork;
this.backgroundWorker.RunWorkerCompleted += HandleBackgroundWorkerOnRunWorkerCompleted;
this.backgroundWorker.WorkerSupportsCancellation = true;
}
private void HandleDataRequest()
{
// show UI notification...
BackgroundWorkUINotification backgroundWorkUINotification = new BackgroundWorkUINotification();
backgroundWorkUINotification.CancelClicked += HandleBackgroundWorkUINotificationOnCancelClicked;
backgroundWorkUINotification.Show(this);
// start the background worker
this.backgroundWorker.RunWorkerAsync();
}
private void HandleBackgroundWorkUINotificationOnCancelClicked(Object sender, EventArgs e)
{
// UI notification Form, Cancelled
// close the form...
BackgroundWorkUINotification backgroundWorkUINotification = (BackgroundWorkUINotification)sender;
backgroundWorkUINotification.Close();
// stop the background worker thread...
if (backgroundWorker.IsBusy)
backgroundWorker.CancelAsync();
}
private void HandleBackgroundWorkerOnRunWorkerCompleted(Object sender, RunWorkerCompletedEventArgs e)
{
}
private void HandleBackgroundWorkerOnDoWork(Object sender, DoWorkEventArgs e)
{
// do some work here..
// also check for CancellationPending property on BackgroundWorker
}
}
答案 3 :(得分:0)
前几天我遇到了同样的麻烦。 这对我很有帮助:"MSDN. How to: Make Thread-Safe Calls to Windows Forms Controls" 我使用了第一个aproach(检查InvokeRequired)因为它是最简单的方法。
希望有用的建议!