Как асинхронно записывать CD / DVD с использованием IMAPI? - PullRequest
1 голос
/ 21 марта 2019

Мне сказали написать программное обеспечение для синхронной / асинхронной записи CD по выбору пользователя. Я использую IMAPIv2 с C # для проекта, и он не предоставляет функции для явной записи данных асинхронно.

Для разработки функциональности я исследовал онлайн-ресурсы, но тщетно.

Может кто-нибудь объяснить, что такое синхронный / асинхронный ввод-вывод с точки зрения записи образа на диск?

Любая помощь приветствуется.

1 Ответ

0 голосов
/ 22 марта 2019

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

...