Как передать прогресс обратно в интерфейс из метода обратного вызова - PullRequest
0 голосов
/ 29 сентября 2019

Я работаю над приложением, которое использует пакет WimgApi Джеффа Клюге для применения образа Windows к диску.

У меня проблемы с получением примера метода обратного вызова для обновления компонентов пользовательского интерфейса, в частностиметка на форме (в идеале - индикатор выполнения).

Я пытался использовать делегат для установки значения, но это, похоже, не работает, так как я не могу понять, как передать делегат в метод обратного вызова.

Если я сделаю метод обратного вызова нестатическим, я смогу получить доступ к свойствам формы, но затем получу тупик, который, даже если я отключу прерывание блокировки, просто заблокируется.

Я имеюмне сказали смотреть на использование IProgress и async, но хотя я могу изменить код для асинхронного запуска метода (это работает и пользовательский интерфейс не блокируется), я все еще не могу понять, как заставить MyCallbackMethod отправлять информацию обратно в пользовательский интерфейс.

//Apply Image Method
public void ApplyImage()
        {
            using (WimHandle wimHandle = WimgApi.CreateFile(@"C:\osimages\test.wim",
                WimFileAccess.Read,
                WimCreationDisposition.OpenExisting,
                WimCreateFileOptions.None,
                WimCompressionType.None))
            {
                // Always set a temporary path
                WimgApi.SetTemporaryPath(wimHandle, Environment.GetEnvironmentVariable("TEMP"));

                // Register a method to be called while actions are performed by WIMGAPi for this .wim file
                WimgApi.RegisterMessageCallback(wimHandle, MyCallbackMethod);

                try
                {
                    // Get a handle to the first image in the .wim file
                    using (WimHandle imageHandle = WimgApi.LoadImage(wimHandle, 1))
                    {
                        // Apply the image contents to C:\Apply
                        // This call is blocking but WIMGAPI will be calling MyCallbackMethod() during the process
                        WimgApi.ApplyImage(imageHandle, @"X:\", WimApplyImageOptions.None);
                    }
                }
                finally
                {
                    // Be sure to unregister the callback method
                    //
                    WimgApi.UnregisterMessageCallback(wimHandle, MyCallbackMethod);
                }
            }

private static WimMessageResult MyCallbackMethod(WimMessageType messageType, object message, object userData)
        {
            switch (messageType)
            {
                case WimMessageType.Progress:  // Some progress is being sent

                    // Get the message as a WimMessageProgress object
                    //
                    WimMessageProgress progressMessage = (WimMessageProgress)message;

                    // UPDATE UI
                    //THIS IS WHERE I WANT TO SEND BACK PROGRESS INFO

                    break;


                   //REMOVED OTHER MESSAGE CASE STATEMENTS TO CONDENSE CODE


            }

            // Depending on what this method returns, the WIMGAPI will continue or cancel.
            //
            // Return WimMessageResult.Abort to cancel.  In this case we return Success so WIMGAPI keeps going

            return WimMessageResult.Success;
        }

//full example code at Example code is https://github.com/jeffkl/ManagedWimgApi/wiki/Message-Callbacks

Если я пытаюсь получить доступ к свойству метки в методе обратного вызова, я получаю 'ссылка на объект требуется для нестатического поля, метода или property form1.progressLabel.text.Я пытался создать делегата, но, похоже, возникли проблемы с доступом к методу при обратном вызове.

Я просмотрел несколько видео и попытался понять документы msdn для делегатов, обратных вызовов и таких вещей, как async / backgroundworkerно я, кажется, просто растерялся.

Действительно ценю любые указатели / вещи, на которых я должен сосредоточиться.

Ответы [ 2 ]

0 голосов
/ 29 сентября 2019

Отказ от ответственности: у меня нет опыта работы с пакетом WimgApi.Но есть перегрузка метода WimgApi.RegisterMessageCallback, принимающего произвольный объект, который будет передан обратному вызову.Поэтому, пожалуйста, попробуйте это:

WimgApi.RegisterMessageCallback(wimHandle, MyCallbackMethod, this);

и в обратном вызове:

var form = (MyForm)userData;
if (form.InvokeRequired)
{
    form.Invoke((MethodInvoker)(() => UpdateProgressUI(...)));
}
else
{
    form.UpdateProgressUI(...);
}
0 голосов
/ 29 сентября 2019

Делая некоторые предположения здесь, но если вы будете показывать только одну форму прогресса за раз, вы сможете избежать хранения статической ссылки на нее.Т.е.:

class ProgressForm
{
    private static ProgressForm staticRef;

    private void Form_Loaded(object sender, EventArgs e)
    {
        staticRef = this;
    }

    private void InternalCallback(uint m, IntPtr w, IntPtr l, IntPtr u)
    {
        // Ensure we're touching UI on the right thread
        if (Dispatcher.InvokeRequired)
        {
            Dispatcher.Invoke(() => InternalCallback(m, w, l, u));
            return;
        }

        // Update UI components
        // ....
    }

    private static uint StaticCallback(uint m, IntPtr w, IntPtr l, IntPtr u)
    {
        staticRef?.InternalCallback(m, w, l, u);

        return 0;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...