【问题标题】:How to invoke a method on specific running task如何在特定运行任务上调用方法
【发布时间】:2019-12-06 10:29:45
【问题描述】:

我是主题任务的新手。

如何访问正确的任务并调用该任务的方法?该任务有一个 ID,我给它一个名称,我得到了一个 TaskScheduler。

我得到了异常,这是正确的: InvalidOperationException:调用线程无法访问此对象,因为该对象由另一个线程拥有。

问题: 在 Main 中,我使用 CustomSplashScreenViewModel.StartSplashScreenAsync() 启动一个任务。更多任务开始并正在运行。当一切都加载完毕后,我需要关闭我的 SplashScreen。

方法CustomSplashScreenViewModel.CloseSplash(_splashTask, _taskSchedulerSplash);获取这些信息。当我调试它时,_splashTask 是“null”并且在 _taskSchedulerSplash 里面有 _splashTask。 在 CloseSplash 方法中,我喜欢在 _splashTask 上调用方法 _view.Close()。

我该如何解决这个问题?

public class Program
{
  private static readonly SingleThreadTaskScheduler _taskSchedulerSplash = new SingleThreadTaskScheduler(ApartmentState.STA);

  [ThreadStatic]
  private static Task _splashTask;

//        [STAThread]
  public static async Task Main()
  {       
    _splashTask = await Task.Factory.StartNew(() =>
    {
        return CustomSplashScreenViewModel.StartSplashScreenAsync();
    }, _taskSchedulerSplash);

    var taskScheduler = new SingleThreadTaskScheduler(ApartmentState.STA);
    var taskList = new List<Task>(); 

    var updateTask = Task.Run(InstallHelper.CheckForUpdatesAsync);
    updateTask.Wait();
    taskList.Add(updateTask);

    var tasks = await Task.Factory.ContinueWhenAll(taskList.ToArray(), result => Task.Factory.StartNew( ()=>AppStart(container), taskScheduler));
        tasks.Wait();
   }


   private static void App_MainWindowLoaded(object sender, EventArgs e)
   {
     CustomSplashScreenViewModel.CloseSplash(_splashTask, _taskSchedulerSplash);
   }
}

public class CustomSplashScreenViewModel
{
  private static Thread _currentThread;
  public static void CloseSplash(Task task, TaskScheduler taskScheduler)
  {
    if (_view!= null)
    {
      // Here i need the right Task and to invoke the following method
      // if I'm doing _view.Dispatcher.Invoke(new Action(_view.Close)); it doesn't 
      // work coz it's another STA Thread. Inside this class I can store the right task in 
      // a local variable. this works. But how to invoke it if the Task is already running?
      // I like to overgive the task - may it isn't possible. 
      _view.Close();      
    }
  }
}

非常感谢你帮助我。

【问题讨论】:

    标签: c# methods task invoke taskscheduler


    【解决方案1】:

    您无法更改正在运行的任务。但是,您可以调度 另一个 将在同一个调度程序上运行的任务,这应该可以满足您的需要(它将在拥有启动画面的同一个 STA 线程上运行):

    public static void CloseSplash(Task task, TaskScheduler taskScheduler)
    {
      if (_view!= null)
      {
        Task.Factory.StartNew(() => _view.Close(), taskScheduler);
      }
    }
    

    顺便说一句,我推荐这些以使代码更易于理解:

    1. 为您的自定义任务调度程序引入 TaskFactory 实例,而不是将 TaskSchedulerTask.Factory 一起使用。
    2. 避免Task.Factory.ContinueWhenAllTask.Wait;请改用Task.WhenAllawait

    【讨论】:

      猜你喜欢
      • 2019-10-27
      • 1970-01-01
      • 1970-01-01
      • 2018-02-10
      • 1970-01-01
      • 2013-12-21
      • 2021-06-19
      • 2022-08-12
      相关资源
      最近更新 更多