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);