C# 总是可以用任务强制一个新线程吗?
每次调用C# 总是可以用任务强制一个新线程吗?,c#,multithreading,C#,Multithreading,每次调用Task.Factory.StartNew时,我都试图创建一个新线程。问题是如何在不引发异常的情况下运行下面的代码: static void Main(string[] args) { int firstThreadId = 0; Task.Factory.StartNew(() => firstThreadId = Thread.CurrentThread.ManagedThreadId);
Task.Factory.StartNew
时,我都试图创建一个新线程。问题是如何在不引发异常的情况下运行下面的代码:
static void Main(string[] args)
{
int firstThreadId = 0;
Task.Factory.StartNew(() => firstThreadId = Thread.CurrentThread.ManagedThreadId);
for (int i = 0; i < 100; i++)
{
Task.Factory.StartNew(() =>
{
while (true)
{
Thread.Sleep(1000);
if (firstThreadId == Thread.CurrentThread.ManagedThreadId)
throw new Exception("The first thread is reused.");
}
});
}
Console.Read();
}
如果指定何时启动任务,则会向调度程序提供提示,默认调度程序会将其作为为任务创建新线程的指示器
这只是一个暗示-我不确定我会相信它。。。但是我还没有看到任何使用默认调度程序的反例。在Jon Skeet的回答中补充说,如果您想保证每次都创建一个新线程,您可以编写自己的
任务调度程序来创建一个新线程。只需使用new thread()启动线程,然后启动它们()
static void Main(字符串[]args)
{
ConcurrentDictionary startedThreads=新建ConcurrentDictionary();
对于(int i=0;i<10;i++)
{
新线程(()=>
{
新线程(()=>
{
startedThreads.AddOrUpdate(Thread.CurrentThread.ManagedThreadId,Thread.CurrentThread.ManagedThreadId,(a,b)=>b);
}).Start();
对于(int j=0;j<100;j++)
{
新线程(()=>
{
while(true)
{
睡眠(10);
if(startedThreads.ContainsKey(Thread.CurrentThread.ManagedThreadId))
Console.WriteLine(“线程重用”);
}
}).Start();
}
}).Start();
}
Console.Read();
}
任务应该由调度程序管理。任务的整体思想是,运行时将决定何时需要新线程。另一方面,如果您确实需要不同的线程,那么代码中可能存在其他错误,例如过度依赖Thread.Sleep()或线程本地存储
如前所述,您可以创建自己的TaskScheduler并使用tasks来创建线程,但为什么要从tasks开始呢?您好,谢谢大家的回答。你们都得到+1。所有建议的解决方案都不适用于我的案例。问题是,当你休眠一个线程时,它会在某个时间点被重用。上述人士建议:
- 如果您有嵌套的/child,那么使用LongRunning=>将不起作用
任务
- 自定义任务调度程序=>我尝试编写自己的任务调度程序,也尝试了这个方法
这也不管用
- 使用纯线程=>仍然失败
- 您也可以在以下位置查看此项目:
我的解决方案
我不喜欢,但它很管用。基本上我阻塞了线程,所以它不能被重用。下面是扩展方法和工作示例。再次感谢你
使用系统;
使用System.Collections.Concurrent;
使用System.Collections.Generic;
使用System.Linq;
使用系统线程;
使用System.Threading.Tasks;
命名空间控制台应用程序
{
公共静态类线程扩展
{
///
///将当前线程阻塞一段时间,以便线程池无法重用该线程。
///
公共静态无效块(此线程,int毫秒)
{
新的WakeSleepClass(毫秒计时)。SleepThread();
}
///
///阻止当前线程,使线程池无法重用该线程。
///
公共静态无效块(此线程)
{
新建WakeSleepClass().SleepThread();
}
///
///将当前线程阻塞一段时间,以便线程池无法重用该线程。
///
公共静态无效块(此线程,TimeSpan超时)
{
新建WakeSleepClass(超时).SleepThread();
}
课堂唤醒睡眠课堂
{
布尔锁定=真;
readonly TimerDisposer TimerDisposer=新TimerDisposer();
公共唤醒睡眠类(int睡眠时间)
{
var timer=新计时器(WakeThread、timerDisposer、sleepTime、sleepTime);
timerDisposer.InternalTimer=计时器;
}
公共唤醒睡眠类(TimeSpan睡眠时间)
{
var timer=新计时器(WakeThread、timerDisposer、sleepTime、sleepTime);
timerDisposer.InternalTimer=计时器;
}
公共类()
{
var timer=新计时器(WakeThread、timerDisposer、Timeout.Infinite、Timeout.Infinite);
timerDisposer.InternalTimer=计时器;
}
public-void-SleepThread()
{
while(锁定)
锁定(timerDisposer)监视器。等待(timerDisposer);
锁定=真;
}
公共线程(对象键)
{
锁定=错误;
锁(键)监视器。脉冲(键);
((TimerDisposer)键).InternalTimer.Dispose();
}
类计时器
{
公共计时器InternalTimer{get;set;}
}
}
}
班级计划
{
私有静态只读队列令牌SourceQueue=新队列();
静态void Main(字符串[]参数)
{
CancellationTokenSource tokenSource=新的CancellationTokenSource();
entqueue(tokenSource);
ConcurrentDictionary startedThreads=新建ConcurrentDictionary();
对于(int i=0;i<10;i++)
{
睡眠(1000);
Task.Factory.StartNew(()=>
{
startedThreads.AddOrUpdate(Thread.CurrentThread.ManagedThreadId,Thread.CurrentThread.ManagedThreadId,(a,b)=>b);
对于(int j=0;j<50;j++)
Task.Factory.StartNew(()=>startedThreads.AddOrUpdate(Thread.CurrentThread.ManagedThreadId
static void Main(string[] args)
{
ConcurrentDictionary<int, int> startedThreads = new ConcurrentDictionary<int, int>();
for (int i = 0; i < 10; i++)
{
Task.Factory.StartNew(() =>
{
Task.Factory.StartNew(() =>
{
startedThreads.AddOrUpdate(Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.ManagedThreadId, (a, b) => b);
}, TaskCreationOptions.LongRunning);
for (int j = 0; j < 100; j++)
{
Task.Factory.StartNew(() =>
{
while (true)
{
Thread.Sleep(10);
if (startedThreads.ContainsKey(Thread.CurrentThread.ManagedThreadId))
Console.WriteLine("Thread reused");
}
}, TaskCreationOptions.LongRunning);
}
});
}
Console.Read();
}
static void Main(string[] args)
{
ConcurrentDictionary<int, int> startedThreads = new ConcurrentDictionary<int, int>();
for (int i = 0; i < 10; i++)
{
new Thread(() =>
{
new Thread(() =>
{
startedThreads.AddOrUpdate(Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.ManagedThreadId, (a, b) => b);
}).Start();
for (int j = 0; j < 100; j++)
{
new Thread(() =>
{
while (true)
{
Thread.Sleep(10);
if (startedThreads.ContainsKey(Thread.CurrentThread.ManagedThreadId))
Console.WriteLine("Thread reused");
}
}).Start();
}
}).Start();
}
Console.Read();
}
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication
{
public static class ThreadExtensions
{
/// <summary>
/// Blocks the current thread for a period of time so that the thread cannot be reused by the threadpool.
/// </summary>
public static void Block(this Thread thread, int millisecondsTimeout)
{
new WakeSleepClass(millisecondsTimeout).SleepThread();
}
/// <summary>
/// Blocks the current thread so that the thread cannot be reused by the threadpool.
/// </summary>
public static void Block(this Thread thread)
{
new WakeSleepClass().SleepThread();
}
/// <summary>
/// Blocks the current thread for a period of time so that the thread cannot be reused by the threadpool.
/// </summary>
public static void Block(this Thread thread, TimeSpan timeout)
{
new WakeSleepClass(timeout).SleepThread();
}
class WakeSleepClass
{
bool locked = true;
readonly TimerDisposer timerDisposer = new TimerDisposer();
public WakeSleepClass(int sleepTime)
{
var timer = new Timer(WakeThread, timerDisposer, sleepTime, sleepTime);
timerDisposer.InternalTimer = timer;
}
public WakeSleepClass(TimeSpan sleepTime)
{
var timer = new Timer(WakeThread, timerDisposer, sleepTime, sleepTime);
timerDisposer.InternalTimer = timer;
}
public WakeSleepClass()
{
var timer = new Timer(WakeThread, timerDisposer, Timeout.Infinite, Timeout.Infinite);
timerDisposer.InternalTimer = timer;
}
public void SleepThread()
{
while (locked)
lock (timerDisposer) Monitor.Wait(timerDisposer);
locked = true;
}
public void WakeThread(object key)
{
locked = false;
lock (key) Monitor.Pulse(key);
((TimerDisposer)key).InternalTimer.Dispose();
}
class TimerDisposer
{
public Timer InternalTimer { get; set; }
}
}
}
class Program
{
private static readonly Queue<CancellationTokenSource> tokenSourceQueue = new Queue<CancellationTokenSource>();
static void Main(string[] args)
{
CancellationTokenSource tokenSource = new CancellationTokenSource();
tokenSourceQueue.Enqueue(tokenSource);
ConcurrentDictionary<int, int> startedThreads = new ConcurrentDictionary<int, int>();
for (int i = 0; i < 10; i++)
{
Thread.Sleep(1000);
Task.Factory.StartNew(() =>
{
startedThreads.AddOrUpdate(Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.ManagedThreadId, (a, b) => b);
for (int j = 0; j < 50; j++)
Task.Factory.StartNew(() => startedThreads.AddOrUpdate(Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.ManagedThreadId, (a, b) => b));
for (int j = 0; j < 50; j++)
{
Task.Factory.StartNew(() =>
{
while (!tokenSource.Token.IsCancellationRequested)
{
if (startedThreads.ContainsKey(Thread.CurrentThread.ManagedThreadId)) Console.WriteLine("Thread reused");
Thread.CurrentThread.Block(10);
if (startedThreads.ContainsKey(Thread.CurrentThread.ManagedThreadId)) Console.WriteLine("Thread reused");
}
}, tokenSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default)
.ContinueWith(task =>
{
WriteExceptions(task.Exception);
Console.WriteLine("-----------------------------");
}, TaskContinuationOptions.OnlyOnFaulted);
}
Thread.CurrentThread.Block();
}, tokenSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default)
.ContinueWith(task =>
{
WriteExceptions(task.Exception);
Console.WriteLine("-----------------------------");
}, TaskContinuationOptions.OnlyOnFaulted);
}
Console.Read();
}
private static void WriteExceptions(Exception ex)
{
Console.WriteLine(ex.Message);
if (ex.InnerException != null)
WriteExceptions(ex.InnerException);
}
}
}
var taskCompletionSource = new TaskCompletionSource<bool>();
Thread t = new Thread(() =>
{
try
{
Operation();
taskCompletionSource.TrySetResult(true);
}
catch (Exception e)
{
taskCompletionSource.TrySetException(e);
}
});
void Operation()
{
// Some work in thread
}
t.Start();
await taskCompletionSource.Task;
public static Task RunInThread(
this Action action,
Action<Thread> initThreadAction = null)
{
TaskCompletionSource<bool> taskCompletionSource = new TaskCompletionSource<bool>();
Thread thread = new Thread(() =>
{
try
{
action();
taskCompletionSource.TrySetResult(true);
}
catch (Exception e)
{
taskCompletionSource.TrySetException(e);
}
});
initThreadAction?.Invoke(thread);
thread.Start();
return taskCompletionSource.Task;
}
public static Task<TResult> RunInThread<T1, T2, TResult>(
this Func<T1, T2, TResult> function,
T1 param1,
T2 param2,
Action<Thread> initThreadAction = null)
{
TaskCompletionSource<TResult> taskCompletionSource = new TaskCompletionSource<TResult>();
Thread thread = new Thread(() =>
{
try
{
TResult result = function(param1, param2);
taskCompletionSource.TrySetResult(result);
}
catch (Exception e)
{
taskCompletionSource.TrySetException(e);
}
});
initThreadAction?.Invoke(thread);
thread.Start();
return taskCompletionSource.Task;
}
var result = await some_function.RunInThread(param1, param2).ConfigureAwait(true);