Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 555 Vote(s) - 3.42 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Simplest way to do a fire and forget method in C#?

#1
I saw in WCF they have the `[OperationContract(IsOneWay = true)]` attribute. But WCF seems kind of slow and heavy just to do create a nonblocking function. Ideally there would be something like static void nonblocking `MethodFoo(){}`, but I don't think that exists.

What is the quickest way to create a nonblocking method call in C#?

E.g.

class Foo
{
static void Main()
{
FireAway(); //No callback, just go away
Console.WriteLine("Happens immediately");
}

static void FireAway()
{
System.Threading.Thread.Sleep(5000);
Console.WriteLine("5 seconds later");
}
}

**NB**: Everyone reading this should think about if they actually want the method to finish. (See #2 top answer) If the method has to finish, then in some places, like an ASP.NET application, you will need to do something to block and keep the thread alive. Otherwise, this could lead to "fire-forget-but-never-actually-execute", in which case,of course, it would be simpler to write no code at all. ([A good description of how this works in ASP.NET][1])


[1]:

[To see links please register here]

Reply

#2
To add to [Will's answer][1], if this is a console application, just throw in an `AutoResetEvent` and a `WaitHandle` to prevent it exiting before the worker thread completes:

Using System;
Using System.Threading;

class Foo
{
static AutoResetEvent autoEvent = new AutoResetEvent(false);

static void Main()
{
ThreadPoolQueueUserWorkItem(new WaitCallback(FireAway), autoEvent);
autoEvent.WaitOne(); // Will wait for thread to complete
}

static void FireAway(object stateInfo)
{
System.Threading.Thread.Sleep(5000);
Console.WriteLine("5 seconds later");
((AutoResetEvent)stateInfo).Set();
}
}


[1]:

[To see links please register here]

Reply

#3
The simplest .NET 2.0 and later approach is using the Asynchnonous Programming Model (ie. BeginInvoke on a delegate):

static void Main(string[] args)
{
new MethodInvoker(FireAway).BeginInvoke(null, null);

Console.WriteLine("Main: " + Thread.CurrentThread.ManagedThreadId);

Thread.Sleep(5000);
}

private static void FireAway()
{
Thread.Sleep(2000);

Console.WriteLine("FireAway: " + Thread.CurrentThread.ManagedThreadId );
}

Reply

#4
Calling beginInvoke and not catching EndInvoke is not a good approach. Answer is simple:
The reason that you should call EndInvoke is because the results of the invocation (even if there is no return value) must be cached by .NET until EndInvoke is called. For example if the invoked code throws an exception then the exception is cached in the invocation data. Until you call EndInvoke it remains in memory. After you call EndInvoke the memory can be released. For this particular case it is possible the memory will remain until the process shuts down because the data is maintained internally by the invocation code. I guess the GC might eventually collect it but I don't know how the GC would know that you have abandoned the data vs. just taking a really long time to retrieve it. I doubt it does. Hence a memory leak can occur.

More can be found on

[To see links please register here]

Reply

#5
For C# 4.0 and newer, it strikes me that the best answer is now given here by Ade Miller:

[To see links please register here]


> Task.Factory.StartNew(() => FireAway());
>
> Or even...
>
> Task.Factory.StartNew(FireAway);
>
> Or...
>
> new Task(FireAway).Start();
>
> Where `FireAway` is
>
> public static void FireAway()
> {
> // Blah...
> }
>
> So by virtue of class and method name terseness this beats the
> threadpool version by between six and nineteen characters depending on
> the one you choose :)
>
> ThreadPool.QueueUserWorkItem(o => FireAway());

Reply

#6
The recommended way of doing this when you are using Asp.Net and .Net 4.5.2 is by using `QueueBackgroundWorkItem`. Here is a helper class:

public static class BackgroundTaskRunner
{
public static void FireAndForgetTask(Action action)
{
HostingEnvironment.QueueBackgroundWorkItem(cancellationToken => // .Net 4.5.2 required
{
try
{
action();
}
catch (Exception e)
{
// TODO: handle exception
}
});
}

/// <summary>
/// Using async
/// </summary>
public static void FireAndForgetTask(Func<Task> action)
{
HostingEnvironment.QueueBackgroundWorkItem(async cancellationToken => // .Net 4.5.2 required
{
try
{
await action();
}
catch (Exception e)
{
// TODO: handle exception
}
});
}
}

Usage example:

BackgroundTaskRunner.FireAndForgetTask(() =>
{
FireAway();
});

or using async:

BackgroundTaskRunner.FireAndForgetTask(async () =>
{
await FireAway();
});

This works great on Azure Web Sites.

Reference: [Using QueueBackgroundWorkItem to Schedule Background Jobs from an ASP.NET Application in .NET 4.5.2][1]


[1]:

[To see links please register here]

Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through