Как я могу вызвать метод в форме из метода, вызванного из внешнего класса из backgroundWorker? Я считаю, что делегаты как-то ответили на этот вопрос, но, потратив время на чтение, я все еще смущен этой проблемой.
Это в Visual Studio 2008, backgroundWorker запускается из формы и вызывает ExternalClass.Method. Форма находится в пространстве имен ProgramName, а ExternalClass использует имя_программы. Когда я объявляю публичный делегат MyDelegate в пространстве имен имя_программы в файле моего windows.form, я могу создать экземпляр MyDelegate и вызвать его в метод моей формы (но это мне не помогает), но если я попытаюсь создать экземпляр MyDelegate и вызывать его из метода моего внешнего класса, я не могу получить доступ к методу окон. форма, даже если она общедоступна.
спасибо
да, я хочу передать отчеты о выполнении (int percent, string status) обратно из ExternalClass.Method. Можете ли вы объяснить немного больше об этом CSharpAtl (или кому-либо)?
Обратите внимание, что ваш вопрос (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");
}
}
Пожалуйста, сделайте себе одолжение и прочитайте BackgroundWorker Component, особенно " Как реализовать форму, использующую фоновый режим.
Другие ресурсы:
Главное понять, что на самом деле у вас на самом деле есть два уровня синхронизации: между Формой и 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
, которое может, в свою очередь, обновить ваше состояние формы.
Обновление: это в основном то же самое, что решение, предложенное Хенком Холтерманом в его новом редактировании.
Я не уверен, в чем проблема. А также вы можете использовать делегат, но не нуждаетесь в нем.
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()
{
}
}