如何从回调方法将进度传回 UI

我正在开发一个应用程序,该应用程序使用 Jeff Kluge 的 WimgApi 包将 Windows 映像应用到磁盘。

我在获取示例回调方法来更新 UI 组件时遇到问题,特别是表单上的标签(最好是进度条)。

我尝试使用委托来设置值,但这似乎不起作用,因为我无法弄清楚如何将委托传递给回调方法。

如果我将回调方法设置为非静态,我可以访问表单属性,但随后我会遇到死锁,即使我禁用死锁打破,它也会锁定。

我被告知要考虑使用 IProgress 和 async,但是虽然我可以更改代码以异步运行该方法(这有效并且 UI 不会锁定),但我仍然无法弄清楚如何让 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);

                }

            }

如果我尝试在回调方法中访问标签属性,我会收到“非静态字段、方法或属性 form1.progressLabel.text 需要对象引用”。我尝试创建委托,但似乎在访问回调中的方法时遇到问题。


我观看了几个视频并尝试了解有关委托、回调和 async/backgroundworker 等内容的 msdn 文档,但我似乎更加困惑。


非常感谢我应该关注的任何指示/事情。


慕的地8271018
浏览 47回答 2
2回答

萧十郎

免责声明:我对 WimgApi 软件包没有任何经验。但是该方法存在重载,WimgApi.RegisterMessageCallback该方法采用将传递给回调的任意对象。所以请尝试这个:WimgApi.RegisterMessageCallback(wimHandle, MyCallbackMethod, this);并在回调中:var form = (MyForm)userData;if (form.InvokeRequired){    form.Invoke((MethodInvoker)(() => UpdateProgressUI(...)));}else{    form.UpdateProgressUI(...);}

森栏

在这里做出一些假设,但如果您一次只显示一个进度表单,那么您应该能够避免存储对其的静态引用。IE: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;    }}
打开App,查看更多内容
随时随地看视频慕课网APP