2012-07-23 18 views
20

मैं एक Winforms आवेदन में निम्न समस्या को ट्रैक करने की कोशिश कर रहा है मुख्य यूआई पर निरंतरता में रिक्त है मुख्य धागा (मुझे उम्मीद है कि वर्तमान सिंक्रनाइज़ेशन संदर्भ System.Windows.Forms.WindowsFormsSynchronizationContext होना चाहिए)।SynchronizationContext.Current धागा

using System; 
using System.Threading; 
using System.Threading.Tasks; 
using System.Windows.Forms; 

namespace WindowsFormsApplication1 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
      TaskScheduler ts = TaskScheduler.FromCurrentSynchronizationContext(); // Get the UI task scheduler 

      // This line is required to see the issue (Removing this causes the problem to go away), since it changes the codeflow in 
      // \SymbolCache\src\source\.NET\4\DEVDIV_TFS\Dev10\Releases\RTMRel\ndp\clr\src\BCL\System\Threading\ExecutionContext.cs\1305376\ExecutionContext.cs 
      // at line 435 
      System.Diagnostics.Trace.CorrelationManager.StartLogicalOperation("LogicalOperation"); 

      var task = Task.Factory.StartNew(() => { }); 
      var cont = task.ContinueWith(MyContinueWith, CancellationToken.None, TaskContinuationOptions.None, ts); 

      System.Diagnostics.Trace.CorrelationManager.StopLogicalOperation(); 
     } 

     void MyContinueWith(Task t) 
     { 
      if (SynchronizationContext.Current == null) // The current SynchronizationContext shouldn't be null here, but it is. 
       MessageBox.Show("SynchronizationContext.Current is null"); 
     } 
    } 
} 

इस के बाद से मैं निरंतरता से BackgroundWorker उपयोग करने का प्रयास है, और BackgroundWorker अपने आयोजनों RunWorkerCompleted और ProgressChanged के लिए वर्तमान SynchronizationContext का उपयोग करेगा मेरे लिए एक मुद्दा है:

यहाँ मुद्दा प्रदर्शन Winforms कोड है। चूंकि जब मैं पृष्ठभूमि वर्कर को लात मारता हूं, तो मौजूदा सिंक्रनाइज़ेशन कॉन्टेक्स्ट शून्य है, इसलिए ईवेंट मुख्य ui थ्रेड पर नहीं चलता है जैसा कि मेरा इरादा है।

मेरा प्रश्न:
इस माइक्रोसॉफ्ट के कोड में एक बग है, या मैं एक गलती कहीं बना दिया है?

अतिरिक्त जानकारी:

  • मैं नेट 4.0 उपयोग कर रहा हूँ (मैं अभी तक .NET 4.5 आर सी पर इस प्रयास नहीं किया है)
  • मैं किसी पर दोनों डीबग/रिलीज पर इस पुन: पेश कर सकते हैं x86/x64/कोई भी CPU (x64 मशीन पर)।
  • यह लगातार पुन: उत्पन्न करता है (अगर कोई इसे पुन: उत्पन्न नहीं कर सकता है तो मुझे दिलचस्पी होगी)।
  • मैं BackgroundWorker का उपयोग करता है विरासत कोड है - तो मैं नहीं आसानी से उपयोग नहीं कर BackgroundWorker
  • मुझे लगता है कि MyContinueWith में कोड मुख्य ui धागा पर चल रहा है की पुष्टि की है करने के लिए बदल सकते हैं।
  • मुझे नहीं पता कि StartLogicalOperation कॉल समस्या का कारण बनने में मदद करता है, यही वह है जो मैंने इसे अपने आवेदन में सीमित कर दिया है।
+0

ठीक है, आपको उस लिंक से निदान मिला है। क्या आप इस विनफॉर्म ऐप में डब्ल्यूपीएफ या डब्ल्यूसीएफ कोड भी मिला रहे हैं? –

+0

नहीं - केवल Winforms। –

उत्तर

20

यह मुद्दा .NET 4.5 आरसी (अभी परीक्षण किया गया है) में तय किया गया है। तो मुझे लगता है कि यह .NET 4.0 में एक बग है। इसके अलावा, मेरा अनुमान है कि यह है कि इन पदों में एक ही मुद्दा संदर्भित कर रहे हैं:

कि दुर्भाग्यपूर्ण है। अब मुझे कामकाज पर विचार करना है।

संपादित करें:
नेट स्रोत में डिबगिंग से, मैं जब इस मुद्दे को दोबारा होगा की एक थोड़ा बेहतर समझ है।

 internal static void Run(ExecutionContext executionContext, ContextCallback callback, Object state, bool ignoreSyncCtx) 
     { 
      // ... Some code excluded here ... 

      ExecutionContext ec = Thread.CurrentThread.GetExecutionContextNoCreate(); 
      if ((ec == null || ec.IsDefaultFTContext(ignoreSyncCtx)) && 
#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK 
       SecurityContext.CurrentlyInDefaultFTSecurityContext(ec) && 
#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK 
       executionContext.IsDefaultFTContext(ignoreSyncCtx)) 
      { 
       callback(state); 
      } 
      else 
      { 
       if (executionContext == s_dummyDefaultEC) 
        executionContext = s_dummyDefaultEC.CreateCopy(); 
       RunInternal(executionContext, callback, state); 
      } 
     } 

समस्या केवल reproduces जब हम "और" खंड जो RunInternal कॉल में मिल: यहाँ ExecutionContext.cs से कुछ प्रासंगिक कोड है।इसका कारण यह है RunInternal समाप्त होता है ExecutionContext जो बदल रहा है जो वर्तमान SynchronizationContext का प्रभाव पड़ता है की जगह है:

 // Get the current SynchronizationContext on the current thread 
     public static SynchronizationContext Current 
     { 
      get 
      { 
       SynchronizationContext context = null; 
       ExecutionContext ec = Thread.CurrentThread.GetExecutionContextNoCreate(); 
       if (ec != null) 
       { 
        context = ec.SynchronizationContext; 
       } 

       // ... Some code excluded ... 
       return context; 
      } 
     } 

तो, मेरी विशेष मामले के लिए, यह था, क्योंकि लाइन `executionContext.IsDefaultFTContext (ignoreSyncCtx)) लौटे असत्य। यहाँ है कि कोड है:

 internal bool IsDefaultFTContext(bool ignoreSyncCtx) 
     { 
#if FEATURE_CAS_POLICY 
      if (_hostExecutionContext != null) 
       return false; 
#endif // FEATURE_CAS_POLICY 
#if FEATURE_SYNCHRONIZATIONCONTEXT 
      if (!ignoreSyncCtx && _syncContext != null) 
       return false; 
#endif // #if FEATURE_SYNCHRONIZATIONCONTEXT 
#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK 
      if (_securityContext != null && !_securityContext.IsDefaultFTSecurityContext()) 
       return false; 
#endif //#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK 
      if (_logicalCallContext != null && _logicalCallContext.HasInfo) 
       return false; 
      if (_illogicalCallContext != null && _illogicalCallContext.HasUserData) 
       return false; 
      return true; 
     } 

मेरे लिए, कि झूठे कारण _logicalCallContext.HasInfo सच था लौट रहा था। यहां वह कोड है:

public bool HasInfo 
{ 
    [System.Security.SecurityCritical] // auto-generated 
    get 
    { 
     bool fInfo = false; 

     // Set the flag to true if there is either remoting data, or 
     // security data or user data 
     if(
      (m_RemotingData != null && m_RemotingData.HasInfo) || 
      (m_SecurityData != null && m_SecurityData.HasInfo) || 
      (m_HostContext != null) || 
      HasUserData 
     ) 
     { 
      fInfo = true; 
     } 

     return fInfo; 
    } 
} 

मेरे लिए, यह सच हो रहा था क्योंकि HasUserData सत्य था। यहाँ है कि कोड है:

internal bool HasUserData 
    { 
     get { return ((m_Datastore != null) && (m_Datastore.Count > 0));} 
    } 

मेरे लिए, m_DataStore Diagnostics.Trace.CorrelationManager.StartLogicalOperation("LogicalOperation");

करने के लिए अपने कॉल सारांश में की वजह से उस में आइटम के लिए होता है, ऐसा लगता है कि वहाँ कई अलग अलग तरीकों आप बग पुन: पेश करने मिल सकता है। उम्मीद है कि यह उदाहरण दूसरों को यह निर्धारित करने में मदद करेगा कि वे इस बग में चल रहे हैं या नहीं।

+1

आप माइक्रोसॉफ्ट पीएसएस से संपर्क कर सकते हैं यह देखने के लिए कि क्या आप इसके लिए हॉटफिक्स प्राप्त कर सकते हैं। –

+3

मैंने यहां एक बग रिपोर्ट सबमिट की है: https://connect.microsoft.com/VisualStudio/feedback/details/755320/synchronizationcontext-current-is-null-in-continuation-on-the-main-ui-thread –

+0

आपकी बग पुन: उत्पन्न नहीं किया गया था :(और माइक्रोसॉफ्ट के एक प्रतिनिधि के बाद यह कहा गया है कि "हम इस मुद्दे को .NETFramework 4.0 पर पुन: उत्पन्न करने में सक्षम थे और पुष्टि की कि यह हमारी अगली रिलीज में तय किया गया है।" मैं जानना चाहता हूं कि यह तय है या नहीं 4.0 में या सिर्फ 4.5। – jpierson

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

  • कोई संबंधित समस्या नहीं^_^