2017-09-16 1 views
0

가 나는 다음과 같은 무언가가 어디에서 일하고 있어요 배경 스레드에서 인스턴스를 주입 액세스 백그라운드 스레드 (Task.Run) 및 Bar은 싱글 톤 라이프 스타일을 사용하여 응용 프로그램의 Main 메서드 (Windows form app)에 등록됩니다. 내가 가진 걱정은 Foo에 제공된 Bar의 구현이 스레드로부터 안전하지 않은 경우입니다.간단한 인젝터 내가 응용 프로그램 내에서 SimpleInjector을 사용하고

내가 가지고있는 주된 문제는 Foo에 의해 필요로하는 상태 인 Bar이며,이 상태는 전에 Foo.DoSomething이 호출되기 전에 주 스레드에 의해 설정됩니다. 나는 내가 직면하고있는이 상황에 대한 해결책을 찾아 보았지만, 도움이되는 사람을 찾을 수 없었다. (나는 이것에 대해 잘못된 방향으로 가고 있지 않다면).

백그라운드 스레드에서 인스턴스가 실행될 때 데코레이터를 사용하는 this 페이지의 제안을 살펴 보았습니다. 그러나 Bar의 상태가 다른 스레드 (주 스레드)에 설정되어 있고 데코레이터를 사용하면 상태가없는 Bar의 새 인스턴스가 작성되므로 도움이되지 않습니다.

그래서 내 질문에 바를 싱글 톤으로 등록해야하고 등록 된 구현이 스레드로부터 안전한지 확인해야한다. 그렇지 않으면이 문제에 대한 명백한 해결책이있다. 나는 볼 수 없습니까?

희망 정보는 충분합니다. 더 자세한 정보가 필요하면 알려주세요.

감사

업데이트 Bar는 단순히 응용 프로그램은 전체에 필요 정보의 목록을 유지하는 클래스입니다. 예를 들어 : 마침내 여기

public partial class App: Form 
{   
    private readonly IFoo _foo; 
    public App(IFoo foo) 
    { 
     InitializeComponent(); 
     _foo = foo;    
    } 

    public btn1_Click() 
    { 
     // This is just for the purpose of showing that the data inside Bar 
     // is loaded on the main thread before Foo.DoSomething is run. In 
     // the real app the Bar data is loaded at previous steps of the app 
     // (the app is a wizard like app). 
     LoadBarData(); 
     Task.Run(() => 
     { 
      _foo.DoSomething(); 
     }); 

     // The issue would be if for example Bar is changed here while the 
     // background thread is running. In my app it doesn't really change 
     // here, but I want to make sure no issues arise in all scenarios, 
     // whether it changes or not.    
    } 
} 

그리고 내 주요 방법입니다 : 바이 등록되어

[STAThread] 
static void Main() 
{ 
    Application.EnableVisualStyles(); 
    Application.SetCompatibleTextRenderingDefault(false); 
    using (Container container = new Container()) 
    { 
     container.Register<IBar, Bar>(Lifestyle.Singleton); 
     container.Register<IFoo, Foo>(Lifestyle.Singleton); 
     container.Register<App>(); 
    } 
    Application.Run(container.GetInstance<App>()); 
} 
+0

바 및 주 관련 코드를 표시하십시오. – Steven

+0

@Steven 더 많은 정보를 포함하도록 질문을 수정했습니다. 희망이 도움이됩니다. 감사합니다 –

답변

0

다음

public class Bar: IBar 
{ 
    // Not using orders or products, but just for purpose of the example 
    // These are initialized early on in the App process because early 
    // steps of the app (which are on the main thread) need them. 
    public IEnumerable<Order> Orders { get; private set; } 

    public IEnumerable<Product> Products { get; private set; } 
} 

내가 푸를 사용하는 형태의 응용 프로그램입니다 싱글 톤 라이프 스타일을 가진 앱의 주요 메소드 (윈도우 폼 앱). Foo에 제공된 Bar의 구현이 스레드로부터 안전하지 않다면 걱정할 필요가 있습니다.

이 경우 응용 프로그램이 Bar에 액세스 병렬로 작업을 실행, 당신은 더 나은 Bar - 그리고 값 확인 스레드 안전 returns- 그것.

Bar 및 그 값이 이고 변경할 수없는 경우이고 응용 프로그램 시작 중에 한 번만 설정하면 문제가되지 않습니다. Bar 또는 그 값을 변경할 수있는 경우 문제가 빠르게 발생하기 시작할 수 있지만 모든 것은 응용 프로그램의 필요에 따라 다릅니다.

  • 싱글 톤이 스레드 안전해야 :

    는 다음과 같은 일반적인 pitfals을 방지하기 위해 수행해야 few general rules 있습니다.

  • 응용 프로그램 코드에서 백그라운드 스레드를 시작하지 마십시오 : 이것을 구성 루트로 이동하십시오.

우리가 처음 언급 한 점. 두 번째 요점은 버튼 클릭 내에서 Task.Run으로 전화하기 때문에 귀하의 경우에도 잘못 될 수 있습니다. 일반적으로 응용 프로그램 코드는 작업이 병렬로 실행되는지 그렇지 않은지에 대해 신경 쓰지 않아야합니다. 이는 주어진 추상화 (이 경우 IFoo) 만 사용해야합니다. 즉, AppTask.Run에 배치하지 않고 _foo.DoSomething();만을 호출해야합니다.

백그라운드 스레드에서 작업을 실행하는 것이 중요한 경우 의 프록시 또는 데코레이터를 호출하여 의 실제 Foo에 대한 호출을 래핑합니다. 이 프록시가 IFoo을 구현할 때 Foo의 스탠드 인으로 사용할 수 있으며 App에 대해 알 필요가 없습니다.

이 모델의 예는 AsyncMailSenderProxyhere입니다.

+0

답장을 보내 주셔서 감사합니다 @ Steven. 막대 상태가 채워지고 초기화 될 때까지 (예를 들어, 앱을 통해 중얼 거림) Bar를 Foo에 삽입하는 것을 지연하려면 어떻게해야합니까? 내가 container.GetInstance를 호출 할 때 Bar가 Foo에 주입되면 데코레이터 메커니즘이 작동하지 않는 것처럼 보입니다 (); 너무 일찍. 감사. –

관련 문제