-3

If I have the following:

public string DoSomethingQuick()
{
  DoSomethingThatTakes10Minutes();
  return "Process Started"; 
}

public void DoSomethingThatTakes10Minutes()
{
/// code to do something that takes 10 minutes
}

How can I alter DoSomethingQuick() so that it returns "Process Started" instantly instead of waiting for DoSomethingThatTakes10Minutes() to complete first?

Palps
  • 568
  • 9
  • 20
  • 2
    See [this answer](http://stackoverflow.com/questions/14455293/async-and-await#answer-19985988) using async and await. – Adam Smith Oct 28 '14 at 23:41
  • May I ask how you found nothing on your searches regarding starting something asynchronous? – default Oct 28 '14 at 23:47
  • Downvoting, because there is no research effort shown in this question. If you have done research but something is unclear, do add it to your question. – default Oct 28 '14 at 23:48
  • Is this in any context, e.g. a Windows application or a website? – HABO Oct 28 '14 at 23:52

2 Answers2

2

One way you could solve this would be to use async and await, like so:

public void Main()
{
    AsyncExample();

    Console.WriteLine("prints first");
}

public async Task AsyncExample()
{
    Task<string> executesSeparately = ExecutesSeparately();

    string result = await longRunningTask;

    Console.WriteLine(result);
}

public async Task<string> ExecutesSeparately()
{
    await Task.Delay(2000);
    return "prints second";
}

As you'll see in the output window, Console.WriteLine("prints first") is executed before AsyncExample() completes and writes a line.

Another way you could solve this is by using a BackgroundWorker.

public string DoSomethingQuick()
{
    var backgroundWorker = new BackgroundWorker();

    backgroundWorker.DoWork += delegate(object s, DoWorkEventArgs args)
    {
         DoSomethingThatTakes10Minutes();
    };

    backgroundWorker.RunWorkerAsync();

    return "Process Started"; 
}

Note that, in a lot of cases, separate threads won't be able to alter non-static objects created from the primary thread, so you'll either need to use the Dispatcher or contain the UI thread logic in a call to BackgroundWorker.ReportProgress(), which automagically works on the UI thread. That would look more like so:

 var backgroundWorker = new BackgroundWorker() { WorkerSupportsCancellation = true };

 backgroundWorker.ReportProgress += delegate(object s, ProgressChangedEventArgs e)
 {
     DoSomethingThatTakes10MinutesAndExecutedOnUiThread();
 }

 backgroundWorker.DoWork += delegate(object s, DoWorkEventArgs e)
 {
     backgroundWorker.ReportProgress(0); // the progress value is irrelevant
 };
furkle
  • 5,019
  • 1
  • 15
  • 24
1

Beside the fact that is pretty ambiguous for a method which should be quick to contain something that should take a long time... You can use a thread to do it

    Thread t;

    public string DoSomethingQuick()
    {
      t=new Thread(DoSomethingThatTakes10Minutes);
      t.isBackground=true;
      t.Start();
      return "Process Started"; 
    }

For more info about Threads: http://msdn.microsoft.com/it-it/library/system.threading.thread(v=vs.110).aspx

Saverio Terracciano
  • 3,885
  • 1
  • 30
  • 42
  • 1
    This is a pretty terrible solution. `t` is scoped local, but the thread itself is application-global. You've also not marked the thread as background, so if the user closes the application UI, the process itself will hang around regardless until the thread completes, at which point you have no idea what might happen. – Polynomial Oct 28 '14 at 23:37
  • Fixed that, I wanted to just give you a quick example on how to use a thread, but you were correct about that. – Saverio Terracciano Oct 28 '14 at 23:40