Supersocketを使用していた古いプロジェクトを古いC++サーバーに更新しました。最後のバージョン(0.7.0 => 0.8.0.8)で再接続しようとしたときに例外が発生しました(ソケットが別のスレッドで開かれたと表示されます)タスクをエンキューするクラスが必要です再接続)し、それらをspedicificスレッドで実行します。特定のスレッドで実行するエンコーディングタスク
私はthisアプローチを見てきましたが、私は例外
ExecuteTask may not be called for a task which was previously queued to a different TaskScheduler.
は、ここで私は
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();
}
}
上記のリンクから撮影したクラスは、ここでどのようにだのGotとして作成したタスクを実行しようとすると、私はその仕事を呼びます
public void RegisterServers()
{
sameThreadTaskScheduler.Queue(new Task(() =>
{
...something
}));
何が悪いのですか? ありがとう
この 'Queue'メソッドの代わりに、タスクスケジューラで' Task.Start(TaskScheduler) '、または' Task.Factory.StartNew'を使ってみてください。 – acelent