如何使用 IMAPI 异步写入 CD/DVD?
How to asynchronously write CD/DVD using IMAPI?
我被告知要编写一个软件来根据用户的选择刻录 CD synchronously/asynchronously。我在项目中使用 IMAPIv2 和 C#,它没有显式提供异步写入数据的功能。
为了设计功能,我研究了网上的资源,但没有成功。
谁能解释一下 Synchronous/Asynchronous I/O 是什么,在光盘上刻录图像?
感谢任何帮助。
IMAPI 不提供内置 class/method 异步写入数据。但它的设计方式使任何支持异步编程的技术都可以实现。您正在使用的那个(您在评论中提到的 C#)确实支持它。
IMAPI 公开那些报告进度和操作状态的接口。您需要做的就是使用线程异步地 运行 和 activity;这将释放您的 UI,您可以进行其他活动。然后,您可以订阅将向您报告状态的事件。
参考 CodeProject 上的 this 项目,它使用 BackgroundWorker
相同:
Multithreading
Burning or formatting media can take some time, so we do not want to perform these actions on the main UI thread. I use the BackgroundWorker
class to handle the multithreading of these lengthy tasks. The BackgroundWorker
class allows you to set values within the thread and then call the ReportProgress
method which fires a ProgressChanged
event in the calling thread. When you are finished with your worker thread, it fires the RunWorkerCompleted
event to notify the calling thread that it is finished.
以下是 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);
}
我被告知要编写一个软件来根据用户的选择刻录 CD synchronously/asynchronously。我在项目中使用 IMAPIv2 和 C#,它没有显式提供异步写入数据的功能。
为了设计功能,我研究了网上的资源,但没有成功。
谁能解释一下 Synchronous/Asynchronous I/O 是什么,在光盘上刻录图像?
感谢任何帮助。
IMAPI 不提供内置 class/method 异步写入数据。但它的设计方式使任何支持异步编程的技术都可以实现。您正在使用的那个(您在评论中提到的 C#)确实支持它。
IMAPI 公开那些报告进度和操作状态的接口。您需要做的就是使用线程异步地 运行 和 activity;这将释放您的 UI,您可以进行其他活动。然后,您可以订阅将向您报告状态的事件。
参考 CodeProject 上的 this 项目,它使用 BackgroundWorker
相同:
Multithreading
Burning or formatting media can take some time, so we do not want to perform these actions on the main UI thread. I use the
BackgroundWorker
class to handle the multithreading of these lengthy tasks. TheBackgroundWorker
class allows you to set values within the thread and then call theReportProgress
method which fires aProgressChanged
event in the calling thread. When you are finished with your worker thread, it fires theRunWorkerCompleted
event to notify the calling thread that it is finished.
以下是 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); }