WinFormHostedService.cs 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. using Microsoft.Extensions.DependencyInjection;
  2. using Microsoft.Extensions.Hosting;
  3. using System;
  4. using System.Threading;
  5. using System.Threading.Tasks;
  6. using System.Windows.Forms;
  7. namespace FastGithub.Windows.Hosting
  8. {
  9. /// <summary>
  10. /// WinForm后台任务和WinForm线程
  11. /// </summary>
  12. /// <typeparam name="TMainForm"></typeparam>
  13. sealed class WinFormHostedService<TMainForm> : IHostedService where TMainForm : Form
  14. {
  15. private readonly Thread staThread;
  16. private readonly IServiceProvider serviceProvider;
  17. private readonly TaskCompletionSource taskCompletionSource = new();
  18. /// <summary>
  19. /// WinForm后台任务
  20. /// </summary>
  21. /// <param name="serviceProvider"></param>
  22. public WinFormHostedService(IServiceProvider serviceProvider)
  23. {
  24. this.serviceProvider = serviceProvider;
  25. this.staThread = new Thread(StaRunMainFrom);
  26. this.staThread.TrySetApartmentState(ApartmentState.STA);
  27. }
  28. /// <summary>
  29. /// 启动
  30. /// </summary>
  31. /// <param name="cancellationToken"></param>
  32. /// <returns></returns>
  33. public Task StartAsync(CancellationToken cancellationToken)
  34. {
  35. this.staThread.Start();
  36. return this.taskCompletionSource.Task;
  37. }
  38. /// <summary>
  39. /// STA线程
  40. /// </summary>
  41. private void StaRunMainFrom()
  42. {
  43. try
  44. {
  45. var mainForm = this.CreateMainForm();
  46. this.taskCompletionSource.TrySetResult();
  47. Application.Run(mainForm);
  48. }
  49. catch (Exception ex)
  50. {
  51. this.taskCompletionSource.TrySetException(ex);
  52. }
  53. }
  54. /// <summary>
  55. /// 实例化MainForm与初始化调度器
  56. /// </summary>
  57. /// <exception cref="InvalidOperationException"></exception>
  58. private TMainForm CreateMainForm()
  59. {
  60. // 在STA线程实例化TMainForm,保证该线程拥有SynchronizationContext
  61. var mainForm = this.serviceProvider.GetRequiredService<TMainForm>();
  62. if (SynchronizationContext.Current is null)
  63. {
  64. throw new InvalidOperationException($"不允许在其它线程上实例化{typeof(TMainForm)}");
  65. }
  66. var dispatcher = this.serviceProvider.GetRequiredService<IWinFormDispatcher>();
  67. dispatcher.SynchronizationContext = SynchronizationContext.Current;
  68. return mainForm;
  69. }
  70. /// <summary>
  71. /// 停止
  72. /// </summary>
  73. /// <param name="cancellationToken"></param>
  74. /// <returns></returns>
  75. public Task StopAsync(CancellationToken cancellationToken)
  76. {
  77. Application.Exit();
  78. return Task.CompletedTask;
  79. }
  80. }
  81. }