Windows 8.1 通用应用程序中 BackgroundWorker 的替代方案是什么? [英] What is the alternative for BackgroundWorker in Windows 8.1 Universal Apps?

查看:31
本文介绍了Windows 8.1 通用应用程序中 BackgroundWorker 的替代方案是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将我的 Windows Phone 应用程序迁移到 Windows 通用应用程序.在 Phone App 中,我使用 BackgroundWorker 进行数据库检索,然后在 UI 中显示.下面是我在 Windows Phone 8 中准备的类以及它是如何调用的.

I am migrating my Windows Phone App to Windows Universal Apps. In Phone App, I used BackgroundWorker for database retrieval and then show in UI. Below is the class which I prepared in Windows Phone 8 and how it was called.

public class TestBackgroundWorker
{
    private BackgroundWorker backgroundWorker;
    ProgressIndicator progressIndicator;

    public delegate void functionToRunInBackground();
    public functionToRunInBackground currentFunctionToExecute;

    public delegate void callbackFunction();
    public callbackFunction functionToSendResult;

    private bool isCancellationSupported;


    private string message;


    /// <summary>
    /// 
    /// </summary>
    /// <param name="functionNameToExecute">specifies function name to be executed in background</param>
    /// <param name="isCancellable">Flag which specifies whether the operation is cancellable or not</param>
    /// <param name="functionNameWhichGetsResult">Specifies call back function to be executed after the completion of operation</param>
    public MCSBackgroundWorker(functionToRunInBackground functionNameToExecute, bool isCancellable, string messageToDisplay, callbackFunction functionNameWhichGetsResult)
    {
        currentFunctionToExecute = functionNameToExecute;
        functionToSendResult = functionNameWhichGetsResult;
        isCancellationSupported = isCancellable;
        message = messageToDisplay;
        backgroundWorker = new BackgroundWorker();
        backgroundWorker.WorkerSupportsCancellation = isCancellable;
        backgroundWorker.DoWork += backgroundWorker_DoWork;
        backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;
    }

    void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        deactivateProgressIndicator();
        functionToSendResult();
    }

    void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        if (currentFunctionToExecute != null)
        {
            currentFunctionToExecute();
        }
    }


    public void cancelBackgroundOperation()
    {
        if (isCancellationSupported == true)
        {
            backgroundWorker.CancelAsync();
        }
    }


    public void Start()
    {
        backgroundWorker.RunWorkerAsync();
        activateProgressIndicator();
    }


    void activateProgressIndicator()
    {
        Deployment.Current.Dispatcher.BeginInvoke(() =>
        {
            var currentPage = App.RootFrame.Content as PhoneApplicationPage;
            SystemTray.SetIsVisible(currentPage, true);
            SystemTray.SetOpacity(currentPage, 0.5);
            SystemTray.SetBackgroundColor(currentPage, Colors.White);
            SystemTray.SetForegroundColor(currentPage, Colors.Black);

            progressIndicator = new ProgressIndicator();
            progressIndicator.IsVisible = true;
            progressIndicator.IsIndeterminate = true;
            progressIndicator.Text = message;

            SystemTray.SetProgressIndicator(currentPage, progressIndicator);

        });

    }

    void deactivateProgressIndicator()
    {
        Deployment.Current.Dispatcher.BeginInvoke(() =>
        {
            if (progressIndicator != null)
            {
                var currentPage = App.RootFrame.Content as PhoneApplicationPage;
                progressIndicator.IsVisible = false;
                SystemTray.SetIsVisible(currentPage, false);

            }

        });
    }


    public bool isBackgroundWorkerBusy()
    {
        return backgroundWorker != null ? backgroundWorker.IsBusy : false;
    }

}

}

并按如下方式调用以在后台运行该进程.

And calling that as below to run the process in background.

private void loadReports()
    {
        bgWorker = new TestBackgroundWorker(loadReportsFromDB, true, "Loading...", showReports);
        bgWorker.Start();
    }

这里,loadReprtsFromDB 和 showReports 是两个函数.

Here, loadReprtsFromDB and showReports are two functions.

问题:

  1. 谁能建议如何在 Windows 8.1 中实现相同的目标?

  1. Can anyone suggest how to achieve same thing in Windows 8.1?

有没有 PhoneApplicationService.Current.State 的替代方案?

Is there any alternative for PhoneApplicationService.Current.State?

推荐答案

恕我直言,即使对于桌面,TaskProgress 类也提供BackgroundWorker 的一个不错的替代品,并且它们都在 Windows Phone 8.1 上受支持.Task 类提供启动然后干净地等待后台操作的机制,而 Progress 类提供报告进度的机制(不属于你的例子或问题,但我提到它是因为这是 Taskasync/await 没有从 BackgroundWorker 提供的一件事).

IMHO, even for the desktop, the Task<T> and Progress<T> classes offer a nice alternative to BackgroundWorker, and they are both supported on Windows Phone 8.1. The Task<T> class provides the mechanism to start and then cleanly wait for background operations, while the Progress<T> class provides the mechanism for reporting progress (not part of your example or question, but I mention it because that's the one thing Task along with async/await doesn't provide from BackgroundWorker).

你的例子可以改成这样:

Your example could be changed to something like this:

public class TestBackgroundWorker
{
    private Task _task;
    private CancellationTokenSource _cancelSource;

    public CancellationToken CancellationToken
    {
        get { return _cancelSource != null ? _cancelSource.Token : null; }
    }

    ProgressIndicator progressIndicator;

    public readonly Action<TestBackgroundWorker> currentFunctionToExecute;

    private string message;

    /// <summary>
    /// 
    /// </summary>
    /// <param name="functionNameToExecute">specifies function name to be executed in background</param>
    /// <param name="isCancellable">Flag which specifies whether the operation is cancellable or not</param>
    /// <param name="functionNameWhichGetsResult">Specifies call back function to be executed after the completion of operation</param>
    public MCSBackgroundWorker(Action<TestBackgroundWorker> functionNameToExecute, bool isCancellable, string messageToDisplay)
    {
        currentFunctionToExecute = functionNameToExecute;
        _cancelSource = isCancellable ? new CancellationTokenSource() : null;
        message = messageToDisplay;
    }

    public void cancelBackgroundOperation()
    {
        if (_cancelSource != null)
        {
            _cancelSource.Cancel();
        }
    }

    public async Task Start()
    {
        activateProgressIndicator();
        _task = Task.Run(() => currentFunctionToExecute(this));
        await _task;
        _task = null;
        deactivateProgressIndicator();
    }

    void activateProgressIndicator()
    {
        // In theory, you should not need to use Dispatcher here with async/await.
        // But without a complete code example, it's impossible for me to
        // say for sure, so I've left it as-is.
        Deployment.Current.Dispatcher.BeginInvoke(() =>
        {
            var currentPage = App.RootFrame.Content as PhoneApplicationPage;
            SystemTray.SetIsVisible(currentPage, true);
            SystemTray.SetOpacity(currentPage, 0.5);
            SystemTray.SetBackgroundColor(currentPage, Colors.White);
            SystemTray.SetForegroundColor(currentPage, Colors.Black);

            progressIndicator = new ProgressIndicator();
            progressIndicator.IsVisible = true;
            progressIndicator.IsIndeterminate = true;
            progressIndicator.Text = message;

            SystemTray.SetProgressIndicator(currentPage, progressIndicator);
        });
    }

    void deactivateProgressIndicator()
    {
        // Likewise.
        Deployment.Current.Dispatcher.BeginInvoke(() =>
        {
            if (progressIndicator != null)
            {
                var currentPage = App.RootFrame.Content as PhoneApplicationPage;
                progressIndicator.IsVisible = false;
                SystemTray.SetIsVisible(currentPage, false);
            }
        });
    }

    public bool isBackgroundWorkerBusy()
    {
        return _task != null;
    }
}

然后你可以像这样使用它:

Then you could use it something like this:

private async Task loadReports()
{
    bgWorker = new TestBackgroundWorker(loadReportsFromDB, true, "Loading...");
    await bgWorker.Start();
    showReports();
}

void loadReportsFromDB(TaskBackgroundWorker worker)
{
    while (...)
    {
        if (worker.CancellationToken.IsCancellationRequested)
        {
            return; // or whatever
        }
    }
}

为了处理取消,functionNameToExecute 委托需要用于接受 TaskBackgroundWorker 实例作为参数的方法,以便它可以检索 CancellationToken 用于检查取消的属性值(类似于 DoWork() 事件处理程序…尽管您的代码示例实际上并未提出任何实际后台操作代码甚至可以检测到的机制取消).

To deal with cancellation, the functionNameToExecute delegate would need to be for a method that accepts an instance of TaskBackgroundWorker as a parameter, so that it can retrieve the CancellationToken property value to check for cancellation (similar to the DoWork() event handler…though your code example didn't actually suggest any mechanism by which the actual background operation code would even detect cancellation).

请注意,使用 async/await,如果您愿意,您的任务也可以通过 Task 类型返回值任务.上面的例子可以很容易地修改以适应这一点,async/await 的特性是我喜欢它而不是 BackgroundWorker 的最大原因之一(它没有从后台操作返回结果的干净的、编译器支持的机制).

Note that with async/await, your task can also return a value if you like, via the Task<T> type instead of Task. The above example could easily be modified to accommodate that, and that feature of async/await is one of the biggest reasons I prefer it over BackgroundWorker (which has no clean, compiler-supported mechanism for returning results from the background operation).

警告: 缺少完整的代码示例作为开始,我没有必要尝试实际编译和测试任何代码.所以以上是严格的浏览器创作".它应该足以用于说明目的,但对于可能存在的任何错别字,我提前道歉.

Caveat: Lacking a complete code example to start with, there is no point for me to try to actually compile and test any of the code. So the above is strictly "browser-authored". It should suffice for the purposes of illustration, but I apologize in advance for any typos that might exist.

这篇关于Windows 8.1 通用应用程序中 BackgroundWorker 的替代方案是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆