使用后台工作者单击了哪个按钮

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;

}