gpt4 book ai didi

c# - Windows 8.1 通用应用程序中 BackgroundWorker 的替代方案是什么?

转载 作者:太空宇宙 更新时间:2023-11-03 10:33:16 27 4
gpt4 key购买 nike

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

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

}

并如下调用它以在后台运行该进程。

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

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

问题:

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

  2. PhoneApplicationService.Current.State 是否有任何替代方案?

最佳答案

恕我直言,即使对于桌面,Task<T>Progress<T>类提供了一个很好的替代 BackgroundWorker , 它们都在 Windows Phone 8.1 上受支持。 Task<T>类提供启动然后干净地等待后台操作的机制,而 Progress<T>类提供报告进度的机制(不是您的示例或问题的一部分,但我提到它是因为这是一件事 Taskasync/await 不提供 BackgroundWorker)。

你的例子可以改成这样:

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

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

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委托(delegate)需要用于接受 TaskBackgroundWorker 实例的方法作为参数,以便它可以检索 CancellationToken用于检查取消的属性值(类似于 DoWork() 事件处理程序……尽管您的代码示例实际上并未建议实际后台操作代码甚至可以检测取消的任何机制)。

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

警告:缺乏完整的代码示例作为开始,我没有必要尝试实际编译和测试任何代码。所以以上是严格的“浏览器创作”。出于说明的目的,它应该足够了,但对于可能存在的任何拼写错误,我提前表示歉意。

关于c# - Windows 8.1 通用应用程序中 BackgroundWorker 的替代方案是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28979590/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com