2010-08-02 13 views
6

वैसे मैंने काम करने के लिए इसे प्राप्त करने के कई तरीकों की कोशिश की है, पृष्ठभूमि कार्यकर्ता, डिस्पैचर। इन्वोक, बुलाया वर्ग के भीतर थ्रेडिंग और काम करने के लिए कुछ भी नहीं लगता है। अब तक का सबसे अच्छा समाधान एक एक्सटेंशन विधि है जो नियंत्रण के आह्वान को बुलाता है। इसके अलावा मैंने अपने इवेंट क्लास के माध्यम से लेबल के लिए डेटा पास करने से बचने की कोशिश की है और बस मेरे प्रसंस्करण कोड के भीतर आविष्कार किया है, हालांकि इससे कोई फर्क नहीं पड़ता।डब्ल्यूपीएफ - प्रसंस्करण के दौरान लेबल सामग्री को अद्यतन करना

पृष्ठभूमि घटक के संबंध में, मैंने पृष्ठभूमि कार्यकर्ता व्यस्त होने के अपवादों को जारी रखा, इसलिए मैंने कई बार कक्षा को तुरंत चालू कर दिया, हालांकि पूरा ऑपरेशन पूरा हो जाने के बाद लेबल केवल स्पष्ट रूप से बदल गया।

मैंने अपना पिछला कोड हटा दिया है, यहां सब कुछ प्रासंगिक है, क्योंकि ऐसा लगता है कि समस्या को हल करना मुश्किल है।

विधि बुलाया जा रहा है

private void TestUris() 
     { 
      string text = new TextRange(rtxturis.Document.ContentStart, rtxturis.Document.ContentEnd).Text; 
      string[] lines = Regex.Split(text.Remove(text.Length - 2), "\r\n"); 

      foreach (string uri in lines) 
      { 
       SafeUpdateStatusText(uri); 
       bool result; 
       string modUri; 

       if (!uri.Contains("http://")) 
       { 
        modUri = uri; 
        result = StoreData.LinkUriExists(new Uri("http://" + modUri)); 
       } 
       else 
       { 

        modUri = uri.Substring(7); 
        result = StoreData.LinkUriExists(new Uri(uri)); 
       } 

       if (!result) 
       { 
        Yahoo yahoo = new Yahoo(); 
        yahoo.Status.Sending += (StatusChange); 
        uint yahooResult = 0; 

        yahooResult = yahoo.ReturnLinkCount(modUri); 

        if (yahooResult > 1000) 
        { results.Add(new ScrapeDetails(Guid.NewGuid(), modUri, 1000, "Will be processed", true)); } 
        else 
        { results.Add(new ScrapeDetails(Guid.NewGuid(), modUri, (int)yahooResult, "Insufficient backlinks", false)); } 

       } 
       else 
       { 
        results.Add(new ScrapeDetails(Guid.NewGuid(), modUri, 0, "Previously been processed", false)); 
       } 
      } 


      foreach (var record in results) 
      { 
       dgvresults.Items.Add(record); 

      } 

      EnableStartButton(); 

     } 

याहू कक्षा

public class Yahoo 
    {   

     /// <summary> 
     /// Returns the amount of links each Uri has. 
     /// </summary> 
     public uint ReturnLinkCount(string uri) 
     { 
      string html; 
      Status.Update(uri, false); //this is where the status is called 
      try 
      { 

       html = client.DownloadString(string.Format("http://siteexplorer.search.yahoo.com/search?p=http%3A%2F%2F{0}&fr=sfp&bwm=i", uri)); 

      } 
      catch (WebException ex) 
      { 
       ProcessError(ex.ToString()); 
       return 0; 
      } 

      return (LinkNumber(html)); 

     } 

स्थिति क्लासेस

public class StatusEventArgs : EventArgs 
    { 
     private string _message; 
     private bool _isidle; 

     public StatusEventArgs(string message, bool isidle) 
     { 
      this._message = message; 
      this._isidle = isidle; 
     } 

     public bool IsIdle 
     { 
      get { return _isidle; } 
     } 

     public string Message 
     { 
      get { return _message; } 
     } 
    } 

    public class Status 
    { 
     public Status() 
     { 
     } 

     // Declaring an event, with a custom event arguments class 
     public event EventHandler<StatusEventArgs> Sending; 

     // Some method to fire the event. 
     public void Update(string message, bool isIdle) 
     { 
      StatusEventArgs msg = new StatusEventArgs(message, isIdle); 
      OnUpdate(msg); 
     } 

     // The method that invokes the event. 
     protected virtual void OnUpdate(StatusEventArgs e) 
     { 
      EventHandler<StatusEventArgs> handler = Sending; 

      if (handler != null) 
      { 
       handler(this, e); 
      } 
     } 
    } 

विधि लेबल सामग्री

private void StatusChange(object sender, StatusEventArgs e) 
     { 

      if(!e.IsIdle) 
      { 
       lblstatus.Content = e.Message; 
       lblstatus.Foreground = StatusColors.Green; 
       lblstatus.Refresh(); 
      } 
      else 
      { 
       lblstatus.Content = e.Message; 
       lblstatus.Foreground = StatusColors.Grey; 
       lblstatus.Refresh(); 
      } 

     } 
परिवर्तन है कि

ताज़ा स्थिर विधि कहा जाता है:

public static class ExtensionMethods 
    { 
     private static Action EmptyDelegate = delegate() { }; 

     public static void Refresh(this UIElement uiElement) 
     { 
      uiElement.Dispatcher.Invoke(DispatcherPriority.Render , EmptyDelegate); 
     } 

एक और संपादित करें: अब थोड़ा के लिए अपने कोड में घूर, मैं, एहसास हुआ है कि foreach लूप वास्तव में जल्दी से निष्पादित करेगा, ऑपरेशन जो समय लेता है,

yahooResult = yahoo.ReturnLinkCount(modUri); 

इसलिए मैंने घोषणा की है स्थिति वर्ग को संपादित करें (जो ईवेंट को संभालता है और लेबल इत्यादि को आमंत्रित करता है) और इसके लिए subscibed। मुझे बेहतर परिणाम मिल गए हैं, हालांकि यह अभी भी यादृच्छिक लगता है, कभी-कभी मुझे कुछ लेबल अपडेट दिखाई देते हैं, और कभी-कभी एक भी सटीक यूआरआई पास हो जाता है, इसलिए अजीब।

+0

इस कोड को एक अलग धागे के अंदर क्रियान्वित कर रहा है? – decyclone

+0

नहीं, दुख की बात है कि मैंने अभी तक इसे ठीक करने में कामयाब नहीं किया है :( – Ash

उत्तर

3

इसे हल हाँ WOOHOOOOOOOO परीक्षण, परीक्षण, परीक्षण के 3 दिन।

मैंने ऊपर विस्तार विधि के साथ एक नई परियोजना शुरू करने का निर्णय लिया और बस यूआई अपडेट कार्यक्षमता का परीक्षण करने के लिए लूप के लिए एक नया प्रोजेक्ट शुरू करने का फैसला किया। मैंने विभिन्न डिस्पैचप्रोराइटियों का परीक्षण शुरू किया (उन सभी का परीक्षण किया)।

अजीब बात यह है कि मैंने पाया कि उच्च प्राथमिकताओं को और भी बदतर था, उदाहरण के लिए प्रेषण का उपयोग लेबल को अपडेट नहीं किया गया था, रेंडर ने इसे औसतन दो बार अपडेट किया था। यह अजीब व्यवहार था जिसे मैं अनुभव कर रहा था क्योंकि मैंने विभिन्न प्राथमिकताओं की कोशिश की थी। मैंने पृष्ठभूमि की खोज की:

गणना मूल्य 4 है। अन्य सभी गैर-निष्क्रिय संचालन पूरा होने के बाद संचालन संसाधित हो जाते हैं।

अब यह वही लगता है जो मैं नहीं चाहता था, क्योंकि स्पष्ट रूप से लेबल को प्रसंस्करण के दौरान अद्यतन करना चाहिए, इसलिए मैंने कभी कोशिश क्यों नहीं की। मैं अनुमान लगा रहा हूं कि मेरी एक विधि में से एक बार पूरा हो जाने के बाद, यूआई अपडेट किया गया है। मुझे अनुमान लगाने का पता चला है, लेकिन यह 100% लगातार दो अलग-अलग परिचालनों पर अपडेट करता है।

धन्यवाद सब कुछ।

+0

मैं इतनी उलझन में हूं .... मुझे एक ही समस्या का सामना करना पड़ रहा है, और इसे समझ नहीं सकता ... केवल विधि के अंत में अद्यतन ... जब लाइन डीबगर में हिट होती है ... कृपया सहायता करें। – Seabizkit

0

क्या इस ऑब्जेक्ट पर किसी संपत्ति के रूप में स्थिति जानकारी जोड़ने के लिए यह आसान/बेहतर होगा, और क्या यह केवल संपत्ति परिवर्तन अधिसूचनाओं को आग लगाना है?

इस तरह लेबल लेबल (या जो भी) एसिंक कार्य करने के बजाय संपत्ति के लिए बाध्य किया जा सकता है लेबल को अद्यतन करने का प्रयास करें?

या अगर आपको इसे अपडेट करना है तो स्थिति अपडेट करने के लिए इस तरह की एक विधि जोड़ें?

void SafeUpdateStatusText(string text) 
    { 
     // update status text on event thread if necessary 
     Dispatcher.BeginInvoke(DispatcherPriority.Background, (SendOrPostCallback)delegate 
     { 
      lblstatus.Content = text; 
     }, null); 
    } 

अन्यथा, मुझे नहीं लगता है हम अभी तक मदद करने के लिए पर्याप्त विवरण है ....

+0

विधि और सलाह जॉन के लिए धन्यवाद। मैंने अलग-अलग डिस्पैच प्राइरीज़ के साथ उस विधि को पांच बार परीक्षण किया है और जब तक मैंने पोस्ट की गई विधि तक लेबल नहीं बदला है उपरोक्त पूरा हो गया है, फिर यह अंतिम यूरी संसाधित करता है। – Ash

+0

इतना यादृच्छिक लगता है, कभी-कभी यह एक अपडेट दिखाता है, कभी-कभी अधिक, इसलिए अजीब विचार है कि मैं एक ही डेटा पास कर रहा हूं और शर्तें भी समान हैं। – Ash

+0

क्या आप इसे दूसरे में कर रहे हैं धागा? आप ब्रेक डाल सकते हैं और सुनिश्चित कर सकते हैं कि आपका यूआई ठीक से अपडेट हो रहा है। यदि आप इसे किसी अन्य थ्रेड में नहीं भेज रहे हैं, तो आप कभी भी यूआई का समय बदलने के लिए नहीं दे रहे हैं? –

5

मुझे उम्मीद है कि वहां sth है। सहायक ...

private void button1_Click(object sender, RoutedEventArgs e) 
{ 
    ThreadPool.QueueUserWorkItem(o => 
    { 
     int result = 0; 
     for (int i = 0; i < 9999999; i++) 
     { 
      result++; 
      Dispatcher.BeginInvoke(new Action(() => 
      { 
       this.label1.Content = result; 
      })); 
      Thread.Sleep(1); 
     } 
    }); 
} 
+0

मैंने इसे एक विधि में डालने की कोशिश की और इसे मेरे WPF ऐप में कॉल करने का प्रयास किया, लेकिन लेबल अभी भी अपडेट नहीं हुआ है। तो मैंने Forms.Aplication.DoEvents() विधि का उपयोग करने का सहारा लिया। कोई मुझे बता सकते हैं क्यों मेरे पद्धति विफल: निजी शून्य SetStatus (स्ट्रिंग स्थिति) { ThreadPool.QueueUserWorkItem (ओ => { Dispatcher.BeginInvoke (नया एक्शन (() => { lblStatus।सामग्री = स्थिति; })); }); } –

3

खैर इस बेवकूफ लग रहा है, लेकिन आप केवल संदर्भ सकता है रूपों नाम स्थान, और उसके बाद आप इस

 using System.Windows.Forms; 

    mylabel = "Start"; 
    Application.doEvents(); 

    myLabel = "update" 
    Application.doEvents(); 

अब समस्या यह का उपयोग कर आप होगा का उपयोग कर रहे क्या कर सकते हैं wpf लेकिन आप अभी भी फॉर्मों का संदर्भ दे सकते हैं और इस नामस्थान का उपयोग कर सकते हैं। दूसरी समस्या यह है कि क्यू में जो भी है वह सीधे यूई को निष्पादित करेगा। हालांकि यह लेबल अपडेट करने का सबसे सरल तरीका है जिसे मैं सोच सकता हूं। मुझे अन्य कारणों के बारे में निश्चित नहीं है कि इसका उपयोग क्यों बुरा होगा लेकिन यह ओपी का समाधान है। यदि आपके पास कोई अच्छा कारण नहीं है, तो वोट कम नहीं है, सिर्फ एक टिप्पणी पोस्ट करके खुद को और अन्य को सूचित करें। धन्यवाद।

+0

केवल तभी काम करता है जब मैं ऐसा करता हूं, ऐसा करने का सही तरीका क्या है? – Seabizkit

0

मुझे आशा है कि इस मदद करता है:

private delegate void UpdateLabelDelegate(DependencyProperty dp, object value); 

public void UpdateLabelContent(Label label, string newContent) 
{ 
    Dispatcher.Invoke(new UpdateLabelDelegate(label.SetValue), DispatcherPriority.Background, ContentProperty, newContent); 
} 

उपयोग:

while (true) 
{ 
    UpdateLabelContent(this.lblStatus, "Next random number: " + new Random().Next()); 
    Thread.Sleep(1000); 
} 
+0

मेनविंडो: विंडो, किसी भी विचार से बुलाया जाने वाला यह काम क्यों नहीं होगा, लाइन को निष्पादित करने के बजाए पूर्ण विधि के बाद ही समाप्त हो जाएगा। – Seabizkit

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