using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Serein.Library.Utils
{
///
/// 为类库提供了在UI线程上下文操作的方法(使用Serein.Workbench时不用处理)
/// 在WPF、Winform项目中,多线程中直接操作UI线程可能发生非预期的异常
/// 所以当你设置自己的平台时,需要手动实例化这个工具类
///
public class UIContextOperation
{
private SynchronizationContext context;
private readonly Func getUiContext = null;
static UIContextOperation()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
}
}
///
/// 传入UI线程上下文
///
/// 线程上下文
public UIContextOperation(SynchronizationContext synchronizationContext)
{
this.context = synchronizationContext;
}
///
/// 传入获取UI线程上下文的闭包创建
///
/// 获取线程上下文的闭包函数
public UIContextOperation(Func getUiContext)
{
this.getUiContext = getUiContext;
}
///
/// 同步方式在UI线程上进行调用方法
///
/// 要执行的UI操作
/// 异常发生时的回调
public void Invoke(Action uiAction, Action onException = null)
{
if(context is null && getUiContext != null)
{
context = getUiContext.Invoke();
}
context?.Post(state =>
{
try
{
uiAction?.Invoke();
}
catch (Exception ex)
{
if(onException != null)
onException(ex);
Debug.WriteLine(ex);
}
}, null);
}
///
/// 异步方式进行调用
///
/// 要执行的UI操作
/// 异常发生时的回调
///
public Task InvokeAsync(Action uiAction, Action onException = null)
{
if (context is null && getUiContext != null)
{
context = getUiContext.Invoke();
}
var tcs = new TaskCompletionSource();
context?.Post(state =>
{
try
{
uiAction?.Invoke();
tcs.SetResult(true);
}
catch (Exception ex)
{
tcs.SetException(ex);
if (onException != null) onException(ex);
Debug.WriteLine(ex);
}
}, null);
return tcs.Task;
}
}
}