35

I have two functions that I want to run on different threads (because they're database stuff, and they're not needed immediately).

The functions are:

            getTenantReciept_UnitTableAdapter1.Fill(rentalEaseDataSet1.GetTenantReciept_Unit);
            getTenantReciept_TenantNameTableAdapter1.Fill(rentalEaseDataSet1.GetTenantReciept_TenantName);

In javascript, I know I can create create an anonymous function and call it on a new thread quite easily with something like this:

setTimeout(new function(){doSomethingImportantInBackground();}, 500);

Is there something like this in C#?

Malfist
  • 31,179
  • 61
  • 182
  • 269
  • 2
    Just an aside, but that Javascript code does **not** call a function on a new thread, it just schedules it to be run in the future. Javascript is single-threaded, so all code runs on the same thread. – BlueRaja - Danny Pflughoeft Feb 28 '16 at 00:44

4 Answers4

76

Your question isn't very clear, I'm afraid. You can easily start a new thread with some code, using anonymous methods in C# 2, and lambda expressions in C# 3:

Anonymous method:

new Thread(delegate() {
    getTenantReciept_UnitTableAdapter1.Fill(
        rentalEaseDataSet1.GetTenantReciept_Unit);
}).Start();
new Thread(delegate() {
    getTenantReciept_TenantNameTableAdapter1.Fill(
        rentalEaseDataSet1.GetTenantReciept_TenantName);
}).Start();

Lambda expression:

new Thread(() =>
    getTenantReciept_UnitTableAdapter1.Fill(
        rentalEaseDataSet1.GetTenantReciept_Unit)
).Start();
new Thread(() =>
    getTenantReciept_TenantNameTableAdapter1.Fill(
        rentalEaseDataSet1.GetTenantReciept_TenantName)
).Start();

You can use the same sort of syntax for Control.Invoke, but it's slightly trickier as that can take any delegate - so you need to tell the compiler which type you're using rather than rely on an implicit conversion. It's probably easiest to write:

EventHandler eh = delegate
{
    // Code
};
control.Invoke(eh);

or

EventHandler eh = (sender, args) =>
{
    // Code
};
control.Invoke(eh);

As a side note, are your names really that long? Can you shorten them to get more readable code?

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • I think the OP wanted each call to Fill() to run on its own thread. But other than that, spot on. – LBushkin Oct 21 '09 at 20:10
  • @LBushkin: Will adjust. It's not a very clear question, to be honest. – Jon Skeet Oct 21 '09 at 20:13
  • I was going to expand my answer to include lambda's but yours is more complete (and better) anyway. A backgroundworker component is still an option, as you don't have to worry about Control.Invoke. – RichardOD Oct 21 '09 at 20:14
  • Okay, nevermaind, I don't have to execute it with Control.invoke. I thought it was earlier throwing an CrossThreadExecution thing-a-majigger – Malfist Oct 21 '09 at 20:14
  • +1 for the comment on the long variable names with little to no actual meaning – snicker Oct 21 '09 at 20:15
  • Okay, I'll update the answer to keep the EventHandler stuff in, but in a slightly different way. – Jon Skeet Oct 21 '09 at 20:15
  • The names are correspond to the Stored Procedure, or the Table that they come from. I don't know why the '1' is appended to them. – Malfist Oct 21 '09 at 20:16
30

Similar to what's been said - I find tasks to be a bit simpler (supported as of .net 4 and can be used as follows as of .net 4.5):

Task mytask = Task.Run(() => 
{
    //Lines of code
});
JSideris
  • 5,101
  • 3
  • 32
  • 50
11

Starting threads is relatively expensive.

You might be better of using a thread from the thread pool:

ThreadPool.QueueUserWorkItem(unused =>
    getTenantReciept_UnitTableAdapter1.Fill(
        rentalEaseDataSet1.GetTenantReciept_Unit)
);
ThreadPool.QueueUserWorkItem(unused =>
    getTenantReciept_TenantNameTableAdapter1.Fill(
        rentalEaseDataSet1.GetTenantReciept_TenantName)
);
oefe
  • 19,298
  • 7
  • 47
  • 66
  • How do you know when the threads are complete? Ie. I did: `ThreadPool.QueueUserWorkItem(unused => data[0] = get_data(a,b));` `ThreadPool.QueueUserWorkItem(unused => data[1] = get_data(a2,b2));` – The Muffin Boy Sep 29 '16 at 15:27
  • 1
    It's 2016 now. 'ThreadPool.QueueUserWorkItem' is so 2009. Use Tasks (see @JSideris) answer, or 'async'. Both provide ways to wait for the task to finish and retrieve a return value. – oefe Sep 29 '16 at 19:44
8

You could use an anonymous method:


void Foo()
{
    Thread myThread = new System.Threading.Thread(delegate(){
              //Your code here
     });
    myThread.Start();
}
Daniel Rodriguez
  • 1,443
  • 12
  • 19
  • 1
    It gives error Cross-thread operation not valid: Control accessed from a thread other than the thread it was created on. – Prakash Vishwakarma Aug 05 '14 at 07:18
  • 1
    @PrakashVishwakarma This is because you are accessing a Control element of your form, but on a different thread than the UI thread. You need to do textboxInput.Invoke(new MethodInvoker(() => { Whatever(); })); and it will schedule the anonymous function () => { Whatever(); } on the UI thread. – Adam White Oct 31 '16 at 20:16