C# 对要在特定线程上运行的任务进行编码 我更新了一个使用超软盘来连接到旧C++服务器的旧项目。对于最新版本(从0.7.0=>0.8.0.8),我在尝试重新连接时遇到了en异常(它表示套接字是在不同的线程上打开的),我希望有一个类将任务排队(第一次连接和重新连接),并在特定的线程上运行它们

C# 对要在特定线程上运行的任务进行编码 我更新了一个使用超软盘来连接到旧C++服务器的旧项目。对于最新版本(从0.7.0=>0.8.0.8),我在尝试重新连接时遇到了en异常(它表示套接字是在不同的线程上打开的),我希望有一个类将任务排队(第一次连接和重新连接),并在特定的线程上运行它们,c#,multithreading,supersocket.net,C#,Multithreading,Supersocket.net,我见过这种方法,但当我尝试运行创建为的任务时,得到了一个异常 对于以前排队到其他TaskScheduler的任务,不能调用ExecuteTask 这是我从上面的链接中选的课程 public class SameThreadTaskScheduler : TaskScheduler, IDisposable { #region publics public SameThreadTaskScheduler(string name) { scheduledTas

我见过这种方法,但当我尝试运行创建为的任务时,得到了一个异常

对于以前排队到其他TaskScheduler的任务,不能调用ExecuteTask

这是我从上面的链接中选的课程

public class SameThreadTaskScheduler : TaskScheduler, IDisposable
{
    #region publics
    public SameThreadTaskScheduler(string name)
    {
        scheduledTasks = new Queue<Task>();
        threadName = name;
    }
    public override int MaximumConcurrencyLevel => 1;

    public void Dispose()
    {
        lock (scheduledTasks)
        {
            quit = true;
            Monitor.PulseAll(scheduledTasks);
        }
    }
    #endregion

    #region protected overrides
    protected override IEnumerable<System.Threading.Tasks.Task> GetScheduledTasks()
    {
        lock (scheduledTasks)
        {
            return scheduledTasks.ToList();
        }
    }

    protected override void QueueTask(Task task)
    {
        if (myThread == null)
            myThread = StartThread(threadName);
        if (!myThread.IsAlive)
            throw new ObjectDisposedException("My thread is not alive, so this object has been disposed!");
        lock (scheduledTasks)
        {
            scheduledTasks.Enqueue(task);
            Monitor.PulseAll(scheduledTasks);
        }
    }

    public void Queue(Task task)
    {
        QueueTask(task);
    }

    protected override bool TryExecuteTaskInline(Task task, bool task_was_previously_queued)
    {
        return false;
    }

    #endregion

    private readonly Queue<System.Threading.Tasks.Task> scheduledTasks;
    private Thread myThread;
    private readonly string threadName;
    private bool quit;

    private Thread StartThread(string name)
    {
        var t = new Thread(MyThread) { Name = name };
        using (var start = new Barrier(2))
        {
            t.Start(start);
            ReachBarrier(start);
        }
        return t;
    }

    private void MyThread(object o)
    {
        Task tsk;
        lock (scheduledTasks)
        {
            //When reaches the barrier, we know it holds the lock.
            //
            //So there is no Pulse call can trigger until
            //this thread starts to wait for signals.
            //
            //It is important not to call StartThread within a lock.
            //Otherwise, deadlock!
            ReachBarrier(o as Barrier);
            tsk = WaitAndDequeueTask();
        }
        for (;;)
        {
            if (tsk == null)
                break;
            TryExecuteTask(tsk);
            lock (scheduledTasks)
            {
                tsk = WaitAndDequeueTask();
            }
        }
    }

    private Task WaitAndDequeueTask()
    {
        while (!scheduledTasks.Any() && !quit)
            Monitor.Wait(scheduledTasks);
        return quit ? null : scheduledTasks.Dequeue();
    }

    private static void ReachBarrier(Barrier b)
    {
        if (b != null)
            b.SignalAndWait();
    }
}

我做错了什么?

您必须启动一个任务才能将其绑定到
任务调度程序。在您的代码中,您正在手动对任务排队,以相反的方式执行,因此任务不会绑定到您的任务计划程序(或任何任务计划程序),并且
TryExecuteTask
将因该错误而失败。描述相当隐晦,因为任何实际的
TaskScheduler
都不同于
null

对于未运行而创建的任务,会出现和的重载,这些重载会占用
任务调度器

对于自动开始运行的任务,存在和的重载,这些重载占用了
任务调度器

对于继续任务,存在和的重载,这些重载使用
TaskScheduler

不接受任务调度器的重载相当于指定。在
任务工厂
的情况下,对于默认值或在调用工厂方法时未创建任务调度器的情况,这是正确的,否则将使用工厂的任务调度器


与较新版本的重载不同,后者总是使用。根据大多数有经验的人的说法,线程池调度程序通常比
任务调度程序更需要作为默认值。当前的
可能是线程绑定的,但更改现有API的契约为时已晚。

尝试使用任务调度程序使用
Task.Start(TaskScheduler)
,或
Task.Factory.StartNew
,而不是此公共
队列
方法。
public void RegisterServers()
{
    sameThreadTaskScheduler.Queue(new Task(() =>
    {
        ...something
    }));