2017-11-30 22 views
2

WPF-MVVM 애플리케이션이 있습니다. asyncawait을 사용하여 파일을로드하고 처리하는 동안 내 UI가 응답하도록하려고합니다. await ed 메소드가 log4net을 사용하여 로깅을 사용할 때 '다른 스레드가 소유하고 있기 때문에 호출하는 스레드가이 객체에 액세스 할 수 없습니다'라는 예외가 발생합니다. 모든 수입이하는log4net으로 로깅 할 때 'Await'이 UI 스레드로 돌아 가지 않습니다.

// The method returns 'void' because it is used by a DelegateCommand! 
private async void LoadAndProcessFileAsync() 
{ 
    this.MyBindingList.Clear(); // Works fine 
    var importer = await Task.Run(() => new Importer()); 
    this.MyBindingList.Clear(); // Exception 
} 

입니다 : 내가 주석 경우

public class Importer 
{ 
    private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 

    public Importer() 
    { 
    log.Info("Test"); 
    } 
} 

log.Info... 및 정적 ILog -variable, 모든 것이 잘 작동합니다. 나는 async 방법에 전혀 await를 사용하지 않는 경우

private async void LoadAndProcessFileAsync() 
{ 
    this.MyBindingList.Clear(); // Works fine 
    var test = await Task.Run(() => Math.Sqrt(9)); 
    var importer = new Importer(); 
    this.MyBindingList.Clear(); // Exception 
} 

그것은 사라 : 다음 작업을 수행 할 경우 문제가 발생합니다.

왜 이런 일이 발생합니까? await을 어떻게 함께 사용할 수 있습니까? (나는 log4net을 사용하는 타사 라이브러리를 사용하고 있으므로 해당 코드를 변경할 수 없습니다 ...).

+3

는 로그 비 정적 할 경우 문제가 발생하지 않습니다 확신 정적 로그는 것을 의미한다 당신은 여러 스레드에서 동일한 객체를 사용하고 있으며, 따라서 왜 주 스레드 (모든 정적 객체를 생성 한 스레드)가 아닌 다른 스레드가 초기화)에 액세스하는 데 문제가 있습니다. – Flater

+2

자신이 소유하지 않은 서드 파티 라이브러리 인 경우 '수입자'가 무엇을하는지 어떻게 알 수 있습니까? – Evk

+0

@Evk : 오류를 재현하기 위해'Importer'를 썼습니다. 타사 라이브러리는 xBim (오픈 소스)이므로, 로깅을 정확히 처리하는지 확인해야합니다. – Timitry

답변

2

비동기 메서드 예제 모두 반환 무효이므로 기다릴 작업이 없기 때문에 최소한 Task를 반환해야하며 '다른 스레드가이 스레드를 소유하고 있기 때문에 호출하는 스레드가이 개체에 액세스 할 수 없습니다. "문제는 디스패처 사용하여보십시오. 새로운 스레드에서 자신의 본질 실행하여

Application.Current.Dispatcher.Invoke(() => {Your Action;}); 

비동기 방법을

+0

'async void'-method가 기다리고 있지 않다는 것은 사실이 아닙니다. 이것은 잘 작동합니다. 나는 당신의 제안을 시도했지만,'Application.Current'는'null'입니다! 그게 내 설치와 관련이있을 수 있습니다, 나는 C#을 Fortran에서 C++/CLI-Wrapper를 통해 호출하고 있습니다 ... 오류가 간단한 C# 응용 프로그램에서 발생하면 시도해야합니다. – Timitry

+1

'본질적으로 비동기 메소드가 새로운 스레드에서 실행된다는 것은 사실이 아닙니다.' 태스크 스케줄러는 적절한 경우 호출 스레드에서 'async' 메소드를 동 기적으로 실행할 수 있습니다. 더 나아가, 스레드를 전혀 필요로하지 않는 IO 바인딩 작업이 있습니다. – dymanoid