С вашего вопроса выясняется, что у вас есть несколько строк в сетке, которые необходимо обработать. Теперь фоновый работник выполняет этот метод в другом потоке, освобождая пользовательский интерфейс для выполнения дополнительных действий. (Обновления статуса IE). Поскольку это выполняется в другом потоке, пользовательский интерфейс может продолжить обработку как обычно. Нить пользовательского интерфейса не будет ждать завершения BackgroundWorker. Если бы это было так, то использование рабочего фона было бы бесполезным. Кроме того, BackgroundWorker должен завершить операцию перед началом другой операции (таким образом, ваше сообщение об ошибке).
Теперь трудно понять, что вы делаете в work.doTheWork()
, но я подозреваю, что вы хотели бы использовать другой подход здесь.
Прежде чем мы начнем решать вопрос, первое, что вы должны понять, это аннулирование фонового работника, фактически не отменившего поток, но предоставляющий «флаг» для вашего кода, чтобы проверить, ожидает ли BackgroundWorker ожидающего вычисления (MSDN on this flag) ,
Перемещение вперед. Поскольку Grid хранится в потоке пользовательского интерфейса, вам нужно понять данные из сетки, которые мы хотим захватить, и передать их в контексте BackgroundWorker. Поскольку этот inst предоставил, я собираюсь сделать очень простой пример. Теперь вы можете запускать несколько фоновых работников для обработки каждой строки отдельно, таким образом, создавая 1 работника в строке в Grid. Для вашего требования это может быть идеальным, но для больших сеток вы по существу создаете 1 поток на строку для обработки, а в сетке с сотнями строк это может быть катастрофическим.
Итак, вы можете создать метод, как показано ниже. Я прокомментировал код, чтобы помочь вам запустить его. Bascially это показывает возможность отменить работника, сообщить о прогрессе и выполнить итерацию каждого элемента строки отдельно. Я также добавил некоторые базовые классы для использования внутри рабочего. [Примечание Это демонстрационный код только]
class DoWorkTester
{
int currentIndex = 0;
GridRow[] rows;
public void ExecuteWorkers()
{
GridRow rowA = new GridRow
{
PropertyA = "abc",
PropertyB = "def"
};
GridRow rowB = new GridRow
{
PropertyA = "123",
PropertyB = "456"
};
GridRow rowC = new GridRow
{
PropertyA = "xyz",
PropertyB = "789"
};
rows = new GridRow[] { rowA, rowB, rowC };
currentIndex = 0;
runWorkers();
}
BackgroundWorker worker;
void runWorkers()
{
//done all rows
if (currentIndex >= rows.Length - 1)
return;
//is the worker busy?
if (worker != null && worker.IsBusy)
{
//TODO: Trying to execute on a running worker.
return;
}
//create a new worker
worker = new BackgroundWorker();
worker.WorkerSupportsCancellation = true;
worker.WorkerReportsProgress = true;
worker.ProgressChanged += (o, e) =>
{
//TODO: Update the UI that the progress has changed
};
worker.DoWork += (o, e) =>
{
if (currentIndex >= rows.Length - 1)
{
//indicate done
e.Result = new WorkResult
{
Message = "",
Status = WorkerResultStatus.DONE
};
return;
}
//check if the worker is cancelling
else if (worker.CancellationPending)
{
e.Result = WorkResult.Cancelled;
return;
}
currentIndex++;
//report the progress to the UI thread.
worker.ReportProgress(currentIndex);
//TODO: Execute your logic.
if (worker.CancellationPending)
{
e.Result = WorkResult.Cancelled;
return;
}
e.Result = WorkResult.Completed;
};
worker.RunWorkerCompleted += (o, e) =>
{
var result = e.Result as WorkResult;
if (result == null || result.Status != WorkerResultStatus.DONE)
{
//TODO: Code for cancelled \ failed results
worker.Dispose();
worker = null;
return;
}
//Re-call the run workers thread
runWorkers();
};
worker.RunWorkerAsync(rows[currentIndex]);
}
/// <summary>
/// cancel the worker
/// </summary>
void cancelWorker()
{
//is the worker set to an instance and is it busy?
if (worker != null && worker.IsBusy)
worker.CancelAsync();
}
}
enum WorkerResultStatus
{
DONE,
CANCELLED,
FAILED
}
class WorkResult
{
public string Message { get; set; }
public WorkerResultStatus Status { get; set; }
public static WorkResult Completed
{
get
{
return new WorkResult
{
Status = WorkerResultStatus.DONE,
Message = ""
};
}
}
public static WorkResult Cancelled
{
get
{
return new WorkResult
{
Message = "Cancelled by user",
Status = WorkerResultStatus.CANCELLED
};
}
}
}
class GridRow
{
public string PropertyA { get; set; }
public string PropertyB { get; set; }
}
Теперь, если вы хотите обработать несколько строк в то время вам придется адаптировать код, чтобы использовать какое-то работник Pooling или передать все данные строки на первый фон таким образом, удаляя рекурсию.
Cheers.
Сколько строк необходимо обрабатывать таким образом? – Steve
Хорошо в ореховой скорлупе вам нужно обновить сетку в завершенном событии. т.е. начать фоновые задания. По завершении каждого результата отображаются результаты. –
Я отредактировал ваш заголовок. Пожалуйста, смотрите: «Если вопросы включают« теги »в их названиях?] (Http://meta.stackexchange.com/questions/19190/), где консенсус« нет, они не должны ». –