TPL Task 객체에서 Dispose ()를 호출하지 않는 것이 허용됩니까?
백그라운드 스레드에서 작업을 실행하도록 트리거하고 싶습니다. 작업 완료를 기다리고 싶지 않습니다.
.net 3.5에서는이 작업을 수행했을 것입니다.
ThreadPool.QueueUserWorkItem(d => { DoSomething(); });
.net 4에서는 TPL이 권장되는 방법입니다. 내가 보았던 일반적인 패턴은 다음과 같습니다.
Task.Factory.StartNew(() => { DoSomething(); });
그러나이 StartNew()
메서드는를 Task
구현 하는 개체를 반환합니다 IDisposable
. 이 패턴을 추천하는 사람들이 간과하는 것 같습니다. 이 Task.Dispose()
방법 에 대한 MSDN 설명서 는 다음과 같이 말합니다.
"작업에 대한 마지막 참조를 해제하기 전에 항상 Dispose에 전화하십시오."
작업이 완료 될 때까지 작업에서 dispose를 호출 할 수 없으므로 기본 스레드 대기 및 호출 dispose를 사용하면 처음부터 백그라운드 스레드에서 수행하는 지점을 물리 칠 수 있습니다. 또한 정리에 사용될 수있는 완료 / 완료된 이벤트가없는 것 같습니다.
Task 클래스의 MSDN 페이지는 이에 대해 언급하지 않으며 "Pro C # 2010 ..."책은 동일한 패턴을 권장하며 작업 처리에 대해서는 언급하지 않습니다.
파이널 라이저가 결국에는 그것을 잡을 수 있다는 것을 알고 있지만, 많은 불을 피우거나 이와 같은 작업을 잊어 버리고 파이널 라이저 스레드가 압도 될 때 이것이 다시 돌아와서 물 릴까요?
그래서 내 질문은 :
- 그것은 호출하지 받아 들일
Dispose()
온Task
이 경우 클래스? 그렇다면, 왜 그리고 위험 / 결과가 있습니까? - 이에 대해 설명하는 문서가 있습니까?
- 아니면
Task
내가 놓친 물건을 처분하는 적절한 방법이 있습니까? - 아니면 TPL로 화재를 피하고 작업을 잊는 다른 방법이 있습니까?
MSDN 포럼에서 이에 대한 토론이 있습니다 .
Microsoft pfx 팀의 구성원 인 Stephen Toub는 다음과 같이 말합니다.
Task.Dispose는 작업이 완료 될 때까지 대기 할 때 사용 된 이벤트 핸들을 잠재적으로 래핑하는 작업으로 인해 대기중인 스레드가 실제로 차단하거나 대기중인 작업을 실행하는 것과는 반대로 차단해야하는 경우에 존재합니다. 당신이하고있는 모든 것이 연속을 사용하고 있다면, 그 이벤트 핸들은 할당되지 않을 것입니다
...
마무리에 의존하여 일을 처리하는 것이 좋습니다.
업데이트 (2012 년 10 월)
Stephen Toub가 작업을 처리해야합니까? 라는 제목의 블로그를 게시했습니다 . 좀 더 자세하게 설명하고 .Net 4.5의 개선 사항을 설명합니다.
요약 : Task
99 %의 시간 동안 물체 를 폐기 할 필요가 없습니다 .
개체를 폐기해야하는 두 가지 주요 이유는 관리되지 않은 리소스를시기 적절하고 결정적인 방식으로 해제하고 개체의 종료자를 실행하는 비용을 피하는 것입니다. 이들 중 어느 것도 Task
대부분의 시간에 적용되지 않습니다 :
- .Net 4.5부터는
Task
내부 대기 핸들 (Task
객체 에서 관리되지 않는 유일한 리소스)을 할당 하는 유일한 시간IAsyncResult.AsyncWaitHandle
은Task
, 및 Task
객체 자체는 종료자가 없습니다; 핸들 자체는 종료자를 사용하여 객체로 래핑되므로 할당되지 않으면 실행할 종료자가 없습니다.
이것은 Thread 클래스와 같은 종류의 문제입니다. 5 개의 운영 체제 핸들을 사용하지만 IDisposable을 구현하지 않습니다. 원래 디자이너의 결정은 물론 Dispose () 메서드를 호출하는 합리적인 방법은 거의 없습니다. 먼저 Join ()을 호출해야합니다.
Task 클래스는 내부 수동 재설정 이벤트 인 핸들 하나를 추가합니다. 가장 저렴한 운영 체제 리소스는 어느 것입니까? 물론 Dispose () 메서드는 Thread가 사용하는 5 개의 핸들이 아니라 하나의 이벤트 핸들 만 해제 할 수 있습니다. 예, 귀찮게하지 마십시오 .
작업의 IsFaulted 속성에 관심을 가져야합니다. 상당히 추악한 주제 입니다. 이 MSDN Library 기사 에서 자세한 내용을 읽을 수 있습니다 . 이 문제를 올바르게 해결하면 코드를 통해 작업을 처리 할 수있는 좋은 위치에 있어야합니다.
누군가 가이 게시물에 표시된 기술에 무게를 두는 것을보고 싶습니다 : C #에서 Typesafe fire-and-forget 비동기 델리게이트 호출
간단한 확장 방법은 작업과 상호 작용하는 모든 사소한 경우를 처리하고 처리를 호출 할 수있는 것처럼 보입니다.
public static void FireAndForget<T>(this Action<T> act,T arg1)
{
var tsk = Task.Factory.StartNew( ()=> act(arg1),
TaskCreationOptions.LongRunning);
tsk.ContinueWith(cnt => cnt.Dispose());
}
'IT박스' 카테고리의 다른 글
Chrome : 백그라운드 탭에서 시간 초과 / 간격이 일시 중지 되었습니까? (0) | 2020.07.20 |
---|---|
3 개의 주요 C ++ 컴파일러에서 프로그램이 다르게 컴파일됩니다. (0) | 2020.07.20 |
개자식 주사에 대한 대안이 있습니까? (0) | 2020.07.20 |
SecItemAdd 및 SecItemCopyMatching은 오류 코드 -34018 (errSecMissingEntitlement)을 반환합니다. (0) | 2020.07.20 |
@Nullable 및 @Nonnull 주석을보다 효과적으로 사용하는 방법은 무엇입니까? (0) | 2020.07.20 |