Все, у меня проблема параллелизма с большим приложением, которое у меня недавно многопоточное. Проблема находится в процессоре сценария, который может запустить пакетных заданийКак сделать глобальный объект Thread-Safe
public async Task<Result> ProcessScriptAsync(
CancellationTokenSource cancelSource,
TaskScheduler uiScheduler)
{
...
// Get instance of active workbook on UI thread.
IWorkbook workbook = this.workbookView.ActiveWorkbook;
while (notFinished)
{
...
Task<bool> runScriptAsyncTask = null;
runScriptAsyncTask = Task.Factory.StartNew<bool>(() =>
{
return RunScript(ref workbook);
}, this.token,
TaskCreationOptions.LongRunning,
TaskScheduler.Default);
// Some cancellation support here...
// Run core asynchroniously.
try
{
bGenerationSuccess = await runScriptAsyncTask;
}
catch (OperationCanceledException)
{
// Handle cancellation.
}
finally
{
// Clean up.
}
}
...
}
Моя проблема возникает, если учесть метод RunScript
. Объект, передаваемый в RunScript
, не является потокобезопасным и был создан в потоке пользовательского интерфейса. Таким образом, я должен создать «глубокую копию» этого объекта внутри метода RunScript
...
private bool RunScript(ref IWorkbook workbook)
{
...
// Get a new 'shadow' workbook with which to operate on from a background thread.
IWorkbook shadowWorkbook;
if (File.Exists(workbook.FullName))
{
// This opens a workbook from disk. The Factory.GetWorkbook method is thread safe.
shadowWorkbook = SpreadsheetGear.Factory.GetWorkbook(workbook.FullName); // (##)
}
else
throw new FileNotFoundException(
"The current workbook is not saved to disk. This is a requirement. " +
"To facilitate multi-threading!");
// Do hard work here...
shadowWorkbook.WorkbookSet.GetLock();
try
{
// Do work and add worksheets to shadowWorkbook.
}
finally
{
// Reassign the UI workbook object to our new shadowWorkbook which
// has been worked on. This is fine to do as not work is actually being
// done on workbook.
workbook = shadowWorkbook;
shadowWorkbook.WorkbookSet.ReleaseLock();
}
}
Моя проблема на линии, отмеченной (##). Каждый раз, когда выполняется RunScript
, создается новый shadowWorkbook
с диска. Проблема заключается в том, что некоторые рабочие листы создаются в shadowWorkbook
, которые впоследствии копируются обратно в workbook
в конце обработки. Однако каждый раз, когда я выполняю RunScript
, я получаю книгу с диска, у которой нет новых листов, сгенерированных в последнем цикле.
Я задумал сделать shadowWorkbook
глобальным объектом, но он создан в потоке пользовательского интерфейса и, следовательно, впоследствии не может использоваться из моей фоновой операции. Один из способов - сохранить книгу на диск после создания каждого рабочего листа, но есть много творений, и это будет дорого.
Есть ли способ сделать shadowWorkbook
глобальной и потокобезопасной, что позволяет мне сохраняться изменения в моей IWorkbook
через нить заклятий?
Спасибо за ваше время.
Может быть [Неустойчивый] (http://msdn.microsoft.com/en-us/library/x13ttww7.aspx) является то, что вы ищете – noobob
@noobob, возможно, нет. Что было бы «неустойчивым» в этой конкретной ситуации? И к какой области он должен применяться? –
Вы хотите изменить файл из нескольких потоков одновременно? Боюсь, что нет простого способа сделать это. – svick