C# 对要在特定线程上运行的任务进行编码 我更新了一个使用超软盘来连接到旧C++服务器的旧项目。对于最新版本(从0.7.0=>0.8.0.8),我在尝试重新连接时遇到了en异常(它表示套接字是在不同的线程上打开的),我希望有一个类将任务排队(第一次连接和重新连接),并在特定的线程上运行它们
我见过这种方法,但当我尝试运行创建为的任务时,得到了一个异常 对于以前排队到其他TaskScheduler的任务,不能调用ExecuteTask 这是我从上面的链接中选的课程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
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
}));