使用后台工作者单击了哪个按钮
Which button was clicked using background worker
我有几个按钮可以使用后台工作程序执行一些操作。我想知道点击了哪个按钮,所以我这样做了:
public MyClass()
{
_worker.DoWork += worker_DoWork;
_worker.RunWorkerCompleted += worker_RunWorkerCompleted;
_worker.ProgressChanged += worker_ProgressChanged;
_worker.WorkerReportsProgress = true;
}
private void First_Button_Click(object sender, RoutedEventArgs e)
{
_worker.RunWorkerAsync();
}
private void Second_Button_Click(object sender, RoutedEventArgs e)
{
_worker.RunWorkerAsync();
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
Button clickedButton = (Button)sender;
switch (clickedButton.Name)
{
case "First_Button":
directory = _ftp.GetCurrentDate(true);
break;
case "Second_Button":
directory = _ftp.GetCurrentDate(false);
break;
case null:
return;
}
}
当我点击其中一个按钮时,我得到 System.InvalidCastException: Unable to cast object of type 'System.ComponentModel.BackgroundWorker' to type 'System.Windows.Controls.Button' .
我知道线程安全调用的重要性,并且我之前在 this site 的帮助下做过这件事,但我不知道如何处理这个问题。请帮忙。
sender
参数是引发事件的对象,因此在您的情况下它将是一个 BackgroundWorker
对象,而不是 Button
。这就是演员表失败的原因。
您可以使用接受对象的重载将按钮名称传递给后台工作程序。然后可以在 DoWork
事件中使用它。
例如:
private void First_Button_Click(object sender, RoutedEventArgs e)
{
_worker.RunWorkerAsync("First_Button");
}
private void Second_Button_Click(object sender, RoutedEventArgs e)
{
_worker.RunWorkerAsync("Second_Button");
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
string buttonName = (string)e.Argument;
switch (buttonName)
{
case "First_Button":
directory = _ftp.GetCurrentDate(true);
break;
case "Second_Button":
directory = _ftp.GetCurrentDate(false);
break;
case null:
return;
}
}
只是想一想,我总是发现为后台工作人员参数创建一个专用 class 是个好主意,这样您就可以在需要时轻松传递多个值。
这是否更接近您要执行的操作?
public Form1()
{
InitializeComponent();
Second_Button.Click += ButtonClick;
First_Button.Click += ButtonClick;
}
private void ButtonClick(object sender, EventArgs e)
{
var directory = String.Empty;
Button clickedButton = (Button)sender;
switch (clickedButton.Name)
{
case "First_Button":
directory = _ftp.GetCurrentDate(true);
break;
case "Second_Button":
directory = _ftp.GetCurrentDate(false);
break;
case null:
return;
}
First_Button.Enabled = false;
Second_Button.Enabled = false;
var bw = new BackgroundWorker();
bw.DoWork += (o, args) =>
{
// your work. You can use directory here
};
bw.RunWorkerCompleted += (o, args) =>
{
First_Button.Enabled = true;
Second_Button.Enabled = true;
};
bw.RunWorkerAsync();
}
甚至更好:
private async void ButtonClick(object sender, EventArgs e)
{
var directory = String.Empty;
Button clickedButton = (Button)sender;
switch (clickedButton.Name)
{
case "First_Button":
directory = _ftp.GetCurrentDate(true);
break;
case "Second_Button":
directory = _ftp.GetCurrentDate(false);
break;
case null:
return;
}
First_Button.Enabled = false;
Second_Button.Enabled = false;
await Task.Run(() =>
{
// your work. you can use directory here
});
First_Button.Enabled = true;
Second_Button.Enabled = true;
}
我有几个按钮可以使用后台工作程序执行一些操作。我想知道点击了哪个按钮,所以我这样做了:
public MyClass()
{
_worker.DoWork += worker_DoWork;
_worker.RunWorkerCompleted += worker_RunWorkerCompleted;
_worker.ProgressChanged += worker_ProgressChanged;
_worker.WorkerReportsProgress = true;
}
private void First_Button_Click(object sender, RoutedEventArgs e)
{
_worker.RunWorkerAsync();
}
private void Second_Button_Click(object sender, RoutedEventArgs e)
{
_worker.RunWorkerAsync();
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
Button clickedButton = (Button)sender;
switch (clickedButton.Name)
{
case "First_Button":
directory = _ftp.GetCurrentDate(true);
break;
case "Second_Button":
directory = _ftp.GetCurrentDate(false);
break;
case null:
return;
}
}
当我点击其中一个按钮时,我得到 System.InvalidCastException: Unable to cast object of type 'System.ComponentModel.BackgroundWorker' to type 'System.Windows.Controls.Button' .
我知道线程安全调用的重要性,并且我之前在 this site 的帮助下做过这件事,但我不知道如何处理这个问题。请帮忙。
sender
参数是引发事件的对象,因此在您的情况下它将是一个 BackgroundWorker
对象,而不是 Button
。这就是演员表失败的原因。
您可以使用接受对象的重载将按钮名称传递给后台工作程序。然后可以在 DoWork
事件中使用它。
例如:
private void First_Button_Click(object sender, RoutedEventArgs e)
{
_worker.RunWorkerAsync("First_Button");
}
private void Second_Button_Click(object sender, RoutedEventArgs e)
{
_worker.RunWorkerAsync("Second_Button");
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
string buttonName = (string)e.Argument;
switch (buttonName)
{
case "First_Button":
directory = _ftp.GetCurrentDate(true);
break;
case "Second_Button":
directory = _ftp.GetCurrentDate(false);
break;
case null:
return;
}
}
只是想一想,我总是发现为后台工作人员参数创建一个专用 class 是个好主意,这样您就可以在需要时轻松传递多个值。
这是否更接近您要执行的操作?
public Form1()
{
InitializeComponent();
Second_Button.Click += ButtonClick;
First_Button.Click += ButtonClick;
}
private void ButtonClick(object sender, EventArgs e)
{
var directory = String.Empty;
Button clickedButton = (Button)sender;
switch (clickedButton.Name)
{
case "First_Button":
directory = _ftp.GetCurrentDate(true);
break;
case "Second_Button":
directory = _ftp.GetCurrentDate(false);
break;
case null:
return;
}
First_Button.Enabled = false;
Second_Button.Enabled = false;
var bw = new BackgroundWorker();
bw.DoWork += (o, args) =>
{
// your work. You can use directory here
};
bw.RunWorkerCompleted += (o, args) =>
{
First_Button.Enabled = true;
Second_Button.Enabled = true;
};
bw.RunWorkerAsync();
}
甚至更好:
private async void ButtonClick(object sender, EventArgs e)
{
var directory = String.Empty;
Button clickedButton = (Button)sender;
switch (clickedButton.Name)
{
case "First_Button":
directory = _ftp.GetCurrentDate(true);
break;
case "Second_Button":
directory = _ftp.GetCurrentDate(false);
break;
case null:
return;
}
First_Button.Enabled = false;
Second_Button.Enabled = false;
await Task.Run(() =>
{
// your work. you can use directory here
});
First_Button.Enabled = true;
Second_Button.Enabled = true;
}