How to asynchronously write CD/DVD using IMAPI?

554 Views Asked by At

I have been told to write a software to burn a CD synchronously/asynchronously as per user choice. I am using IMAPIv2 with C# for the project, and it does not provide the functionality explicitly to write the data asynchronously.

In order to design the functionality, I have researched online resources, but in vain.

Can someone explain what Synchronous/Asynchronous I/O is, in terms of burning an image on a disc?

Any help is appreciated.

1

There are 1 best solutions below

0
On BEST ANSWER

IMAPI does not provide in-build class/method to write data asynchronously. But it is designed a way that it is possible with any technology that supports asynchronous programming. The one you are using (C# as you mentioned in comments) does support it.

IMAPI exposes interfaces those report status for progress and actions. All you need to do is use the threading to run the activity asynchronously; this will free up your UI and you can perform other activities. Then, you may subscribe for the events those will report the status to you.

Refer this project on CodeProject which uses BackgroundWorker for the same:

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.

Following are DoWork and Update events:

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);
}