如何解决如何从 C# 类库中的颜色在 UWP 中创建 SolidColorBrush?
我有一个 UWP 应用,它有 XAML 页面和类库来帮助聚合某些功能。
我有某些对象(动态)具有名为 Brush 的属性。此属性包含可在 XAML 中绑定的任何 Brush,以指示用于使用此画笔在控件内绘制控件/项的画笔。这一切都封装在各种转换器中,以便在绑定期间使用。
我遇到了几个问题:
-
从非 UI 调度程序运行转换器会引发“Marshalled For Another Thread”错误。
return Task.Run(async () => await Data.CreateSolidColorBrush(color)).Result;
这是 Data.CreateSolidColorBrush 函数的代码:
public async static Task<Brush> CreateSolidColorBrush(Color color)
{
Brush brush = null;
var dispatcher = Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.dispatcher;
//var dispatcher = Window.Current.dispatcher;
await dispatcher.RunAsync(CoredispatcherPriority.normal,() =>
{
try { brush = new SolidColorBrush(color); }
catch (Exception ex)
{ }
});
return brush;
}
我尝试了各种异步/任务/动作/等方法,但有些根本不运行动作,有些会导致死锁。
从一种颜色创建画笔的最佳方法是什么,没有所有的复杂性!
解决方法
首先:
return Task.Run(async () => await Data.CreateSolidColorBrush(color)).Result;
可以简化为:
return Data.CreateSolidColorBrush(color).Result;
关于死锁:
Dispatcher.RunAsync
将 lambda 放在调度程序中的待处理工作列表中,并返回一个 Task
,在工作完成时将完成。
您等待任务,因此您将等待其完成。但是您可能在调度程序的线程上,它等待您继续执行挂起的工作。这是一个死锁。
在调用 RunAsync
之前,您应该检查您是否不在 UI 线程上,如果您在 UI 线程上,则立即执行。
最后,我什至不确定您是否需要在 UI 线程上构建画笔。所以测试一下你什么时候会有一个工作代码。
关于Marshalled For Another Thread
:
您没有显示任何代码。如果以上内容不能解决问题,请使用调度程序通过 RunAsync
设置视图属性。同样,您将不得不测试您是否在 UI 线程上。
如果您在 UI 线程上或通过调度程序,请参阅 https://stackoverflow.com/a/63376211/361177 以获取帮助程序进行测试并立即执行操作。
,我能够使用以下代码修复它:
公共异步静态任务 CreateSolidColorBrush(Color color)
{
Brush brush = null;
Threading.ThreadSafe(() => brush = new SolidColorBrush(color));
if (brush == null)
{
Threading.ThreadSafe(() =>
{
try { brush = new SolidColorBrush(color); }
catch (Exception Ex)
{ }
}
);
}
return brush;
}
public static class Threading
{
private static CoreDispatcher Dispatcher =>
Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher;
public static async void ThreadSafe(DispatchedHandler action)
{
// Calls Dispatcher.RunAsync to run a method on the Main UI Thread
IAsyncAction UiThread(DispatchedHandler proc) => Dispatcher.RunAsync(CoreDispatcherPriority.Normal,proc);
// Checks to see if this was called from the Main UI thread
// If we are in the Main UI thread then Invoke the action
// Otherwise: Send it to run in the Main Ui Thread.
if (Dispatcher.HasThreadAccess)
{
action.Invoke();
}
else
{
await UiThread(action);
}
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。