Как я могу вызвать метод в форме из метода, вызванного из внешнего класса из backgroundWorker?

2

Как я могу вызвать метод в форме из метода, вызванного из внешнего класса из backgroundWorker? Я считаю, что делегаты как-то ответили на этот вопрос, но, потратив время на чтение, я все еще смущен этой проблемой.

Это в Visual Studio 2008, backgroundWorker запускается из формы и вызывает ExternalClass.Method. Форма находится в пространстве имен ProgramName, а ExternalClass использует имя_программы. Когда я объявляю публичный делегат MyDelegate в пространстве имен имя_программы в файле моего windows.form, я могу создать экземпляр MyDelegate и вызвать его в метод моей формы (но это мне не помогает), но если я попытаюсь создать экземпляр MyDelegate и вызывать его из метода моего внешнего класса, я не могу получить доступ к методу окон. форма, даже если она общедоступна.

спасибо

да, я хочу передать отчеты о выполнении (int percent, string status) обратно из ExternalClass.Method. Можете ли вы объяснить немного больше об этом CSharpAtl (или кому-либо)?

  • 0
    Вы хотите, чтобы внешний класс мог что-то сигнализировать вызывающему классу? Если это так, вы можете поместить событие в фоновый рабочий класс, на который подписывается вызывающий класс.
Теги:
class
delegates
backgroundworker
visual-studio-2008

4 ответа

0
Лучший ответ

Обратите внимание, что ваш вопрос (afaik) касается не только справочника, но и того, как разбить круговую ссылку между классами. Это стандартная проблема со стандартным решением.

Вы можете передать делегат (ссылаясь на метод формы) вокруг так же, как и любой объект, а также на Работника Фонового Рабочего. И Bgw может передать его внешнему методу. Делегат включает ссылку на объект (в данном случае на форму).

Обратите внимание, что поскольку вы находитесь в другом потоке, вам нужно будет использовать Control.Invoke внутри делегата или использовать событие Bgw ReportProgress.

public partial class Form1 : Form
{
    private void ReportProgresshandler(int percent, string state)
    {
        backgroundWorker1.ReportProgress(percent);  // also does the Invoke
    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        var ex = new ExampleClass();
        ex.Dowork(ReportProgresshandler);    
    }
}

и что-то вроде

class ExampleClass
{
    delegate void ReportDelegate(int percent, string status);

    public void Dowork(ReportDelegate report)
    {
        report(0, "starting");
    }

}
  • 0
    Просто чтобы прояснить, вам нужно использовать метод формы «s Invoke (), не Delegate.Invoke ().
  • 0
    Yoooder: хорошая мысль, абсолютно. Я обошел его используя ReportProgress.
2

Пожалуйста, сделайте себе одолжение и прочитайте BackgroundWorker Component, особенно " Как реализовать форму, использующую фоновый режим.

Другие ресурсы:

1

Главное понять, что на самом деле у вас на самом деле есть два уровня синхронизации: между Формой и BackgroundWorker, а также между BackgroundWorker и объектом ExternalClass.

Форма асинхронно вызывает BackgroundWorker.DoWork(), которая работает в другом потоке. Любые обновления формы должны проходить через Form.Invoke() (который вызывает произвольный делегат в потоке формы) или, еще лучше, через событие BackgroundWorker.ProgressChanged (которое запускает определенное событие в потоке формы).

Итак, что вы хотите сделать, это прокси-сервер обновления статуса из метода ExternalClass обратно в BackgroundWorker, который, в свою очередь, подталкивает их к форме. Один из способов сделать это в прошлом - использовать делегат обратного вызова:

public delegate void ProgressCallback(double percentCompleted, string status);

И пусть мой дорогой метод-работник принимает обратный вызов в качестве аргумента:

public void ExpensiveMethod(ProgressCallback callback) {
    while(doingThings) {
        if(callback != null) callback(percentDone, statusString);
    }
}

Затем в вашем классе BackgroundWorker определите метод, соответствующий вашему делегату callback, и позвоните ему BackgroundWorker.ReportProgress(), чтобы запустить событие BackgroundWorker.ProgressChanged, которое может, в свою очередь, обновить ваше состояние формы.

Обновление: это в основном то же самое, что решение, предложенное Хенком Холтерманом в его новом редактировании.

0

Я не уверен, в чем проблема. А также вы можете использовать делегат, но не нуждаетесь в нем.

using System.Windows.Forms;
using System.ComponentModel;

public partial class ExampleForm : Form
{

    public ExampleForm()
    {
        InitializeComponent();

        var worker = new BackgroundWorker();
        worker.DoWork += new DoWorkEventHandler(doWork);
        worker.RunWorkerAsync(this);
    }

    void doWork(object sender, DoWorkEventArgs e)
    {
        ExampleForm f = e.Argument as ExampleForm;
        f.Hello();
    }

    private void Hello()
    {

    }

}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню