全体として、最近マルチスレッド化した大規模なアプリケーションで同時実行の問題が発生しました。問題は、バッチ ジョブを実行できるスクリプト プロセッサ内にあります。
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
はスレッドセーフではなく、UI スレッドで作成されました。そのため、メソッド内でこのオブジェクトの「ディープ コピー」を作成する必要があります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
ましたが、UI スレッドで作成されるため、バックグラウンド操作から使用できません。これを回避する 1 つの方法は、ワークシートを作成するたびにワークブックをディスクに保存することですが、作成数が多く、コストが高くなります。
shadowWorkbook
グローバルでスレッド セーフにする方法はありIWorkbook
ますか?
御時間ありがとうございます。