WCF에서 [OperationContract(IsOneWay = true)]
속성이 있습니다. 그러나 WCF는 비 차단 기능을 만들기 위해 느리고 무겁습니다. 이상적으로는 static void nonblocking과 같은 것이 MethodFoo(){}
있지만 나는 존재하지 않는다고 생각합니다.
C #에서 비 차단 메서드 호출을 만드는 가장 빠른 방법은 무엇입니까?
예 :
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 :이 글을 읽는 모든 사람들이 실제로 방법을 끝내기를 원한다면 생각 해봐야합니다. (# 2 상위 답변 참조)이 방법을 완료해야하는 경우 ASP.NET 응용 프로그램과 같은 일부 위치에서 스레드를 활성 상태로 유지하고 차단하기위한 작업을 수행해야합니다. 그렇지 않으면 이로 인해 “불을 잊었지만 결코 실제적으로 실행되지 않을 수 있습니다”.이 경우 코드를 전혀 작성하지 않는 것이 더 간단합니다. ( 이것이 ASP.NET에서 어떻게 작동하는지에 대한 좋은 설명 )
답변
ThreadPool.QueueUserWorkItem(o => FireAway());
(5 년 후…)
Task.Run(() => FireAway());
luisperezphd가 지적한 대로 .
답변
C # 4.0 이상에서는 Ade Miller가 최고의 답변을 얻었습니다 .C # 4.0에서 가장 쉬운 방법은 화재를 잊고 방법을 잊는 것입니다.
Task.Factory.StartNew(() => FireAway());
또는…
Task.Factory.StartNew(FireAway);
또는…
new Task(FireAway).Start();
어디
FireAway
있다public static void FireAway() { // Blah... }
따라서 클래스 및 메소드 이름 간결성으로 인해 선택한 문자에 따라 스레드 풀 버전이 6 ~ 19 자 사이입니다. 🙂
ThreadPool.QueueUserWorkItem(o => FireAway());
답변
.NET 4.5의 경우 :
Task.Run(() => FireAway());
답변
Will의 답변에 추가하려면 콘솔 응용 프로그램 인 경우 작업자 스레드가 완료되기 전에 AutoResetEvent
a 및 a WaitHandle
를 던져 종료되지 않도록하십시오.
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();
}
}
답변
쉬운 방법은 매개 변수가없는 람다로 스레드를 만들고 시작하는 것입니다.
(new Thread(() => {
FireAway();
MessageBox.Show("FireAway Finished!");
}) {
Name = "Long Running Work Thread (FireAway Call)",
Priority = ThreadPriority.BelowNormal
}).Start();
ThreadPool.QueueUserWorkItem에서이 메소드를 사용하면 디버깅하기 쉽게 새 스레드의 이름을 지정할 수 있습니다. 또한 디버거 외부에서 처리되지 않은 예외가 발생하면 응용 프로그램이 갑자기 중단되므로 루틴에서 광범위한 오류 처리를 사용하는 것을 잊지 마십시오.
답변
Asp.Net 및 .Net 4.5.2를 사용할 때 권장되는 방법은을 사용하는 것 QueueBackgroundWorkItem
입니다. 다음은 도우미 클래스입니다.
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
}
});
}
}
사용 예 :
BackgroundTaskRunner.FireAndForgetTask(() =>
{
FireAway();
});
또는 비동기 사용 :
BackgroundTaskRunner.FireAndForgetTask(async () =>
{
await FireAway();
});
이것은 Azure 웹 사이트에서 훌륭하게 작동합니다.
참조 : QueueBackgroundWorkItem을 사용하여 .NET 4.5.2의 ASP.NET 응용 프로그램에서 백그라운드 작업 예약
답변
beginInvoke를 호출하고 EndInvoke를 잡는 것은 좋은 방법이 아닙니다. 대답은 간단합니다. EndInvoke를 호출해야하는 이유는 EndInvoke가 호출 될 때까지 호출 결과 (반환 값이없는 경우에도)가 .NET에 의해 캐시되어야하기 때문입니다. 예를 들어, 호출 된 코드에서 예외가 발생하면 예외가 호출 데이터에 캐시됩니다. EndInvoke를 호출 할 때까지 메모리에 남아 있습니다. EndInvoke를 호출 한 후 메모리를 해제 할 수 있습니다. 이 특정한 경우에, 호출 코드에 의해 데이터가 내부적으로 유지되기 때문에 프로세스가 종료 될 때까지 메모리가 남아있을 수 있습니다. 나는 GC가 결국 그것을 모을지도 모른다고 생각하지만 GC가 데이터를 버렸다는 사실을 어떻게 알지 모르겠다. 나는 그것을 의심한다. 따라서 메모리 누수가 발생할 수 있습니다.
자세한 내용은 http://haacked.com/archive/2009/01/09/asynchronous-fire-and-forget-with-lambdas.aspx 에서 찾을 수 있습니다 .