Files
serein-flow/Library/Utils/UIContextOperation.cs

121 lines
3.6 KiB
C#
Raw Normal View History

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