2013-03-08 8 views
6

वर्ग नीचे दिए गए, एक वैकल्पिक धागा पर स्प्लैश स्क्रीन शुरू करने के लिए की TPL समतुल्य:थ्रेड क्लास 'स्पलैश प्रकार' स्क्रीन

public partial class SplashForm : Form 
{ 
    private static Thread _splashThread; 
    private static SplashForm _splashForm;  

    public SplashForm() 
    { 
     InitializeComponent(); 
    } 

    // Show the Splash Screen (Loading...)  
    public static void ShowSplash()  
    {   
     if (_splashThread == null)   
     {    
      // Show the form in a new thread.   
      _splashThread = new Thread(new ThreadStart(DoShowSplash));    
      _splashThread.IsBackground = true;    
      _splashThread.Start();   
     }  
    }  

    // Called by the thread. 
    private static void DoShowSplash()  
    {   
     if (_splashForm == null)    
      _splashForm = new SplashForm();  

     // Create a new message pump on this thread (started from ShowSplash).  
     Application.Run(_splashForm); 
    }  

    // Close the splash (Loading...) screen. 
    public static void CloseSplash()  
    {   
     // Need to call on the thread that launched this splash.  
     if (_splashForm.InvokeRequired)    
      _splashForm.Invoke(new MethodInvoker(CloseSplash));   
     else    
      Application.ExitThread();  
    } 
} 

यह कहा जाता है और निम्नलिखित संबंधित आदेशों के साथ बंद कर दिया है

SplashForm.ShowSplash(); 
SplashForm.CloseSplash(); 

ठीक है।

Task task = Task.Factory.StartNew(() => 
{ 
    SomeForm someForm = new SomeForm(); 
    someForm.ShowDialog(); 
}; 

मेरे इस मुद्दे को इस SomeForm नीचे बंद हो रहा है जब आप तैयार हैं:

मैं बिल्कुल TPL के लिए नया नहीं हूँ, बेशक हम के रूप में सरल कुछ का उपयोग कर एक और धागा पर प्रपत्र दिखा सकते हैं। वहाँ की तरह

private static SomeForm _someForm; 
public static void CloseSomeForm()  
{   
    if (_someForm.InvokeRequired)    
     _someForm.Invoke(new MethodInvoker(CloseSomeForm));   
} 

मेरा प्रश्न है, SomeForm कक्षा में एक public static विधि बनाने की तुलना में एक बेहतर तरीका होना चाहिए क्या एक ही बात करने के लिए सबसे अच्छा तरीका है के रूप में कार्य समानांतर लाइब्रेरी का उपयोग करके उपरोक्त SplashForm वर्ग का उपयोग कर दिखाया है (TPL)? विशेष रूप से, यूआई से दूसरे धागे पर लगाए गए फॉर्म को बंद करने का सबसे अच्छा तरीका।

+0

क्या है उद्देश्य स्प्लैश स्क्रीन को किसी अन्य धागे पर डाल रहा है? –

+1

इसे सक्रिय रखने के लिए (एनिमेशन दिखाएं आदि)। यूआई को अवरुद्ध न करें। – MoonKnight

उत्तर

2

आपका प्रश्न Thread और Task के बीच एक अंतर के बारे में इतना प्रतीत नहीं होता है क्योंकि आप "गंदा" स्थिर स्थिति से छुटकारा पाने के लिए क्या चाहते हैं। मेरा सुझाव है कि आप इसे कक्षा में समाहित करें:

class SplashController 
{ 
    public void Run() { 
     _someForm = new SomeForm(); 
     someForm.ShowDialog(); 
    } 

    private SomeForm _someForm; 
    public void CloseSomeForm()  
    {   
     if (_someForm.InvokeRequired)    
      _someForm.Invoke(new MethodInvoker(CloseSomeForm));   
    } 
} 

आप जो भी थ्रेडिंग तंत्र का उपयोग कर रन को कॉल कर सकते हैं। CloseSomeForm थ्रेडिंग का उपयोग नहीं करता है, इसलिए यह इस समस्या से स्वतंत्र है।

अब आप कहीं भी SplashController के उदाहरण के संदर्भ में एक संदर्भ संग्रहीत कर सकते हैं। स्थानीय चर या वास्तव में स्थिर चर में। उत्तरार्द्ध समझ में आता है क्योंकि बिल्कुल एक स्पलैश स्क्रीन है।

क्योंकि स्थिर स्थिति अब अच्छी तरह से encapsulated है, मुझे स्थिर रूप से आयोजित होने के साथ कोई समस्या नहीं दिख रही है।

+0

महान जवाब, बहुत अच्छा विचार, बिल्कुल नहीं सोचा !? जो मैंने पहले किया था उसके लिए मेरी मुख्य पकड़ 'InvokeRequired' का उपयोग था। मुझे लगता है कि जो कुछ मैं चाहता हूं उसके लिए एक और अच्छा तंत्र नहीं है। – MoonKnight

+1

टीपीएल के पास TaskScheduler.FromCurrentSynchronizationContext का उपयोग करके यूआई थ्रेड पर एक कॉल मार्शल करने का एक तरीका है। दुर्भाग्यवश, शेड्यूलर प्राप्त करने के लिए यूआई थ्रेड पर इस विधि को कॉल किया जाना चाहिए। तो इसका उपयोग करने के लिए आपको इसे यूआई थ्रेड पर प्राप्त करने के लिए एक नृत्य करना होगा और इसे अपने अन्य धागे पर ले जाना होगा। मैं इसकी सिफारिश नहीं करता। – usr

+0

मुझे 'टास्कशेड्यूलर' मार्ग से अवगत है, लेकिन इस मामले में आपके द्वारा बताए गए कारणों से यह अच्छा नहीं है। उपर्युक्त में मुझे लगता है कि आप 'रन() {_ कुछफॉर्म = नया कुछफॉर्म(); ...} 'चाहते थे। – MoonKnight

2

आप शायद इस

Task task = Task.Factory.StartNew(() => 
{ 
    SomeForm someForm = new SomeForm(); 
    someForm.ShowDialog(); 
}; 

की तरह कुछ ऐसा नहीं करना चाहिए, क्योंकि यह संदेश पाश की आवश्यकता होगी सटीक धागा कि फार्म है, जो एक ThreadPool धागा है बनाता है पर उपस्थित होने के लिए। लेकिन मैंने इसका परीक्षण नहीं किया है।

आप इस कोशिश कर सकते:

// Close the splash (Loading...) screen. 
public void CloseSplash()  
{   
    // Need to call on the thread that launched this splash.  
    if (this.InvokeRequired)    
     this.Invoke(new MethodInvoker(CloseSplash));   
    else    
     Application.ExitThread();  
} 

इस तरह इस्तेमाल किया जा सकता है:

public static Task<SplashForm> ShowSplash()  
{   
    var tcs = new TaskCompletionSource<SplashForm>(); 

    // Show the form in a new thread.   
    _splashThread = new Thread(() => 
    { 
     var splashForm = new SplashForm();  

     tcs.SetResult(_splashForm); 

     // Create a new message pump on this thread (started from ShowSplash).  
     Application.Run(splashForm); 
    }); 

    _splashThread.IsBackground = true;    
    _splashThread.Start();   
}  

यह आप CloseSplash से स्थिर संशोधक को दूर करने की अनुमति होगी

var form = await SplashForm.ShowSplash(); 
form.CloseSplash(); 
+0

मुझे यह पसंद है। आपके समय के लिए धन्यवाद। – MoonKnight

+0

ध्यान दें कि SetResult सिंक्रनाइज़ रूप से निष्पादित हो सकता है और आपको अजीब व्यवहार हो सकता है, इस बात के आधार पर कि आप क्या करते हैं, इसके बाद आप एप्लिकेशन को हिट नहीं कर सकते हैं। लाइन लाइन जब आपको लगता है कि आपको चाहिए। यदि संदेह है, तो एक अलग कार्य (टास्क.रुन के साथ) पर SetResult लोड करें। –

+0

@bluesman आपको अपनी टिप्पणी के साथ मेरा ध्यान मिला। थोड़ा और समझाने की देखभाल? – Joel

संबंधित मुद्दे