IMAPI не предоставляет встроенный класс / метод для асинхронной записи данных.Но он разработан таким образом, что это возможно с любой технологией, которая поддерживает асинхронное программирование.Тот, который вы используете (C #, как вы упомянули в комментариях), поддерживает его.
IMAPI предоставляет интерфейсы, которые сообщают о состоянии отчета для прогресса и действий.Все, что вам нужно сделать, это использовать потоки для асинхронного выполнения действия;это освободит ваш пользовательский интерфейс, и вы сможете выполнять другие действия.Затем вы можете подписаться на события, которые сообщат вам о состоянии.
См. этот проект на CodeProject, который использует BackgroundWorker
для того же:
Многопоточность
Запись или форматирование носителя может занять некоторое время, поэтому мы не хотим выполнять эти действия в основном потоке пользовательского интерфейса.Я использую класс BackgroundWorker
для обработки многопоточности этих длинных задач.Класс BackgroundWorker
позволяет вам устанавливать значения в потоке, а затем вызывать метод ReportProgress
, который запускает событие ProgressChanged
в вызывающем потоке.Когда вы закончили работу с вашим рабочим потоком, он запускает событие RunWorkerCompleted
, чтобы уведомить вызывающий поток о том, что он завершен.
Ниже приведены события DoWork
и Update
:
private void backgroundBurnWorker_DoWork(object sender, DoWorkEventArgs e)
{
MsftDiscRecorder2 discRecorder = null;
MsftDiscFormat2Data discFormatData = null;
try
{
//
// Create and initialize the IDiscRecorder2 object
//
discRecorder = new MsftDiscRecorder2();
var burnData = (BurnData)e.Argument;
discRecorder.InitializeDiscRecorder(burnData.uniqueRecorderId);
//
// Create and initialize the IDiscFormat2Data
//
discFormatData = new MsftDiscFormat2Data
{
Recorder = discRecorder,
ClientName = ClientName,
ForceMediaToBeClosed = _closeMedia
};
//
// Set the verification level
//
var burnVerification = (IBurnVerification)discFormatData;
burnVerification.BurnVerificationLevel = _verificationLevel;
//
// Check if media is blank, (for RW media)
//
object[] multisessionInterfaces = null;
if (!discFormatData.MediaHeuristicallyBlank)
{
multisessionInterfaces = discFormatData.MultisessionInterfaces;
}
//
// Create the file system
//
IStream fileSystem;
if (!CreateMediaFileSystem(discRecorder, multisessionInterfaces, out fileSystem))
{
e.Result = -1;
return;
}
//
// add the Update event handler
//
discFormatData.Update += discFormatData_Update;
//
// Write the data here
//
try
{
discFormatData.Write(fileSystem);
e.Result = 0;
}
catch (COMException ex)
{
e.Result = ex.ErrorCode;
MessageBox.Show(ex.Message, "IDiscFormat2Data.Write failed",
MessageBoxButtons.OK, MessageBoxIcon.Stop);
}
finally
{
if (fileSystem != null)
{
Marshal.FinalReleaseComObject(fileSystem);
}
}
//
// remove the Update event handler
//
discFormatData.Update -= discFormatData_Update;
if (_ejectMedia)
{
discRecorder.EjectMedia();
}
}
catch (COMException exception)
{
//
// If anything happens during the format, show the message
//
MessageBox.Show(exception.Message);
e.Result = exception.ErrorCode;
}
finally
{
if (discRecorder != null)
{
Marshal.ReleaseComObject(discRecorder);
}
if (discFormatData != null)
{
Marshal.ReleaseComObject(discFormatData);
}
}
}
void discFormatData_Update([In, MarshalAs(UnmanagedType.IDispatch)] object sender,
[In, MarshalAs(UnmanagedType.IDispatch)] objectprogress)
{
//
// Check if we've cancelled
//
if (backgroundBurnWorker.CancellationPending)
{
var format2Data = (IDiscFormat2Data)sender;
format2Data.CancelWrite();
return;
}
var eventArgs = (IDiscFormat2DataEventArgs)progress;
_burnData.task = BURN_MEDIA_TASK.BURN_MEDIA_TASK_WRITING;
// IDiscFormat2DataEventArgs Interface
_burnData.elapsedTime = eventArgs.ElapsedTime;
_burnData.remainingTime = eventArgs.RemainingTime;
_burnData.totalTime = eventArgs.TotalTime;
// IWriteEngine2EventArgs Interface
_burnData.currentAction = eventArgs.CurrentAction;
_burnData.startLba = eventArgs.StartLba;
_burnData.sectorCount = eventArgs.SectorCount;
_burnData.lastReadLba = eventArgs.LastReadLba;
_burnData.lastWrittenLba = eventArgs.LastWrittenLba;
_burnData.totalSystemBuffer = eventArgs.TotalSystemBuffer;
_burnData.usedSystemBuffer = eventArgs.UsedSystemBuffer;
_burnData.freeSystemBuffer = eventArgs.FreeSystemBuffer;
//
// Report back to the UI
//
backgroundBurnWorker.ReportProgress(0, _burnData);
}