1

우리는 클라이언트까지 확장하는 클라이언트 클래스를 보유하고 있습니다.이 경쟁 조건을 방지하는 방법은 무엇입니까?

protected void Proxy() 
    { 
     Error = null; 
     _proxy = new WebServiceClient<T>(_fullURL); 
     Error = _proxy.Error; 
    } 

    protected virtual void Cleanup() 
    { 
     if (_proxy != null) 
     { 
      _proxy.Dispose(); 
      _proxy = null; 
     } 
    } 

을 그리고 클라이언트 병렬로 호출되는 몇 가지 작업을 포함

BaseClass로이 방법이 있습니다. 클라이언트은 싱글 톤이 아니므로 매번 하나의 인스턴스를 생성합니다.

public void OperationAsync(Action<BaseResult> callback) 
{ 

    TaskCompletionSource<String> taskSrc = new TaskCompletionSource<String>(); 
    Task<String> tsk = taskSrc.Task; 
    try 
    { 
     Proxy(); 

     ThreadPool.QueueUserWorkItem(t => 
     { 
      try 
      { 
       String result = _proxy.Channel.ExecuteOperation(SecurityToken()); 
       taskSrc.SetResult(result); 
      } 
      catch (Exception ex) 
      { 
       taskSrc.SetException(ex); 
      } 
     }); 

     tsk.Wait(); 

     BaseResult r = new BaseResult(); 
     r.Value = tsk.Result; 
     r.Error = tsk.Exception; 
     Cleanup(); 

     if (callback != null) 
     { 
      callback(r); 
     } 

    } 
    catch (Exception ex) 
    { 
     FileManager.Log(ex); 
    } 
} 

당신이 볼 수 있듯이, 각각의 작업이 프록시정리 작업을 호출

작업은 같다.

우리는 때때로 (어쩌면 하루에 한 번) 우리가 로그 파일에서이 오류를 참조 아직 행동의 패턴을 발견,하지만하지 않았다

는 :

하나 이상의 오류가 발생 ..의 InnerException : System.ObjectDisposedException를 : 수 없다 배치 된 객체에 접근한다. 개체 이름 : 'System.ServiceModel.Channels.ServiceChannel'.

특정 작업에서는 발생하지 않습니다. 그것은 항상 변합니다. 프록시는 생성자와 처리 중에 수행해야한다고 생각하지만 여러 가지를 변경해야한다는 것을 의미하므로 확실하게 알고 싶습니다.

나는 그것을 개선 할 수있는 방법에 대해 정말로 감사 할 것입니다.

+1

? 왜'Proxy'가'WebServiceClient '을 함수에 로컬 변수에 저장 한 다음 그 변수를'Cleanup'에 전달하지 않도록하십시오. 또한, 백그라운드 작업자는 함수 호출에 추가 오버 헤드를 추가하는 것 외에는 아무 것도하지 않습니다. 다른 스레드에 작업을 넣으려고한다면 immedatly 그 스레드에 대해'.Wait()'를 호출하면 끝난다. 그런 다음 여분의 스레드를 전혀 사용하지 않을 때 항상 성능이 저하 될 것이다. –

+1

코드에서'catch (Exception ex)'를 쓰는 것을 정말로 중단해야합니다. 그냥 버그를 소개합니다. 복구 할 수있는 예외는 예외적 인 경우에만 잡아야합니다. [Eric Lippert의 Vexing Exceptions] (https://blogs.msdn.microsoft.com/ericlippert/2008/09/10/vexing-exceptions/)를 읽으십시오. – Enigmativity

+0

여기에서 경쟁 조건을 얻으려면 동일한 인스턴스에서 여러 번 OperationAsync를 호출해야하며 (명령문에 따라 다르지는 않음) 정적 멤버로 _proxy를 사용해야합니다. 들). 따라서 경쟁 조건은 표시되지 않은 코드에서 실제로 다른 원인을 가진 것 같습니다 (즉, 개별 인스턴스에서 한 번 이상 OperationAsync를 호출). –

답변

1

원래 코드는 tsk.Wait(); 이었으므로 백그라운드 스레드에서 프록시 코드를 실행하는 동안 호출 스레드를 차단하고있었습니다. 이렇게하면 이익이 증가하고 오버 헤드가 증가 할 가능성이 있습니다.

그래서, 여기에 경쟁 조건을 방지하는 방법은 다음과 같습니다

모든 필드를 _proxy``왜
public void OperationAsync(Action<BaseResult> callback) 
{ 
    try 
    { 
     var r = new BaseResult(); 
     using (var proxy = new WebServiceClient<T>(_fullURL)) 
     { 
      try 
      { 
       r.Value = proxy.Channel.ExecuteOperation(SecurityToken()); 
      } 
      catch (Exception ex) 
      { 
       r.Error = ex; 
      } 
     } 
     if (callback != null) 
     { 
      callback(r); 
     } 
    } 
    catch (Exception ex) 
    { 
     FileManager.Log(ex); 
    } 
} 
관련 문제