5

The following code throws an exception 99% of the time.

How can I ensure a new thread is created with Task.Run?

int e;
void Main()
{
    Task.Run(() => 
    {
        e = Thread.CurrentThread.ManagedThreadId;
        Task.Run(() => {CheckThread();}).Wait();
    }).Wait();

    Console.WriteLine("finish");
}

void CheckThread()
{
   if(e == Thread.CurrentThread.ManagedThreadId)
   {
      throw new Exception("Error: " + Thread.CurrentThread.ManagedThreadId);
   }
}
Servy
  • 202,030
  • 26
  • 332
  • 449
user2746029
  • 59
  • 1
  • 2
  • Would you mind the share with us the exception you get? Also, Task and threads are two different things. I would suggest you read a bit about the topic https://stackoverflow.com/questions/4130194/what-is-the-difference-between-task-and-thread – Crispy Holiday Sep 29 '17 at 14:56
  • He throws an exception if the previous Task has the same thread ID as the task he calls inside it. The problem is the task is probably created in a new thread but since its not doing enough work the 2nd task doesn't create a new thread. I don't know if both tasks are necessary in this example. – Sam Marion Sep 29 '17 at 14:59
  • 2
    Why do you have problem with a thread pool thread being used here, and why is it important that you have a different thread pool thread for these two operations? If you're doing something in this code that makes it *essential* that you have different threads here then that's a problem, and should most likely be re-designed. Of course the code shouldn't depend on them using the same thread either, it should be designed to be ambivalent and to work regardless of whether the same or a different thread is used. – Servy Sep 29 '17 at 15:09
  • This is just an example. My real application is much more complex. I have a long running task and in this task I use Task.Run to get data from a database. – user2746029 Sep 29 '17 at 15:10
  • 3
    @user2746029 You shouldn't be using `Task.Run` to perform IO bound work. There's no reason to create an additional thread at all. The DB provider you're using should be providing inherently asynchronous operations for querying the database. Use those instead of creating a thread just for it to do nothing but sit around waiting and not doing anything productive. – Servy Sep 29 '17 at 15:11
  • Okay..I am using Ninject and I have some classes binded to THREAD scope. If I use my service locator to get a new instance of a class I get in both tasks the same object. – user2746029 Sep 29 '17 at 15:20
  • 1
    Not totally clear what you mean here but if that is a problem then they shouldn't have thread scope. – H H Sep 29 '17 at 15:40

1 Answers1

7

This code will run the Task code in a new thread

var t = new Task(CheckThread, TaskCreationOptions.LongRunning);
t.Start();
t.Wait();

But please be aware that this is behavior is not documented. So, if you want to be sure you are creating a thread, you must create one yourself

One way to do this, while using a Task to know when the thread has finished

var tcs = new TaskCompletionSource<object>();
var thread = new Thread(() =>
{
    CheckThread();
    tcs.SetResult(null);
} );
thread.Start();
tcs.Task.Wait();
Tiago Sousa
  • 953
  • 5
  • 14
  • 1
    Why the downvote? I've answered the OP question. Please provide your feedback so others can improve their answers – Tiago Sousa Sep 29 '17 at 16:07
  • Probably because the question is about the behaviour of the Task.Run method and whether it always creates new threads. You didn't answer that. – kristianp Sep 19 '18 at 07:34
  • 5
    The question was "How can I ensure a new thread is created with Task.Run?"... I think I've answered that. The why was not the question. – Tiago Sousa Sep 22 '18 at 17:53