c# सी#संकलन त्रुटि: "आवेज़ या ब्वॉयइनवोक को तब तक नियंत्रित नहीं किया जा सकता जब तक कि खिड़की का संचालन नहीं हो।"




delegates invoke (8)

मैं सिर्फ एक प्रश्न पोस्ट करता हूं कि एक टेक्स्ट को किसी अन्य फ़ॉर्म पर अपडेट करने के लिए एक प्रतिनिधि कैसे प्राप्त करें। जब मैंने सोचा था कि मुझे जवाब देने का जवाब था ... ऐसा होता है यहां मेरा कोड है:

मुख्य फ़ॉर्म कोड:

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;
using System.Data.OleDb;
using System.Collections.Specialized;
using System.Text;
using System.Threading;

delegate void logAdd(string message);

namespace LCR_ShepherdStaffupdater_1._0
{
    public partial class Main : Form
    {
        public Main()
        {
            InitializeComponent();
        }

        public void add(string message)
        {
            this.Log.Items.Add(message);
        }
        public void logAdd(string message)
        {   /////////////////////////// COMPILER ERROR BELOW ///////////
            this.Invoke(new logAdd(add), new object[] { message }); // Compile error occurs here     
        }////////////////////////////// COMPILER ERROR ABOVE ///////////

        private void exitProgramToolStripMenuItem_Click(object sender, EventArgs e) 
        {
            Application.Exit(); 
        }
        private void aboutToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            Form aboutBox = new AboutBox1(); 
            aboutBox.ShowDialog(); 
        }

        private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
        {
        }

        private void settingsToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            settingsForm.settings.ShowDialog();
        }

        private void synchronize_Click(object sender, EventArgs e)
        {
            string message = "Here my message is"; // changed this
            ErrorLogging.updateLog(message);  // changed this
        }

    }

    public class settingsForm 
    {
        public static Form settings = new Settings();
    }

}

लॉगिंग वर्ग कोड:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LCR_ShepherdStaffupdater_1._0
{
    public class Logging
    {
        static Main mainClass = new Main();
        static logAdd logAddDelegate;

        public static void updateLog(string message)
        {
            logAddDelegate = mainClass.logAdd;
            logAddDelegate(message);
        }
    }
}
  • त्रुटि संकलित करें:

    अमान्यऑपरेशन अपवाद अनियंत्रित था - निमंत्रण या बग़लइनवोक को नियंत्रण पर नहीं बुलाया जा सकता जब तक विंडो हैंडल नहीं बनाया गया हो।

मैंने पहले से लॉग आइटम पर एक हैंडल बनाने का प्रयास किया ... लेकिन वह काम नहीं कर रहा था। समस्या यह है कि मेरे पास कोई सचेत नहीं है जो मैं कर रहा हूं और मैंने Google को बड़े पैमाने पर केवल अस्पष्ट उत्तर ढूंढने के लिए खोजा है।

कृपया मुझे बताएं कि इससे पहले कि मैं इस प्रतिनिधि को आमंत्रित करूँगा, इससे पहले कि संभाल कैसे करें। जब आप उस पर हैं, तो मुझे कुछ तरीके बताओ कि मैं यह कोड अधिक सरल बना सकता हूं। उदाहरण के लिए, मैं दो कार्यों को जोड़ना नहीं चाहता ... मुझे ऐसा करना पड़ा क्योंकि लॉगिंग क्लास से आग्रह करने के लिए कोई आइटम खोजने के लिए मेरे पास कोई रास्ता नहीं था। क्या मुझे पूरा करने का एक बेहतर तरीका है?

धन्यवाद!!!

संपादित करें:

मेरी परियोजना काफी बड़ी है, लेकिन ये एकमात्र ऐसी विशिष्ट समस्याएं पैदा करने वाले आइटम हैं।

लॉग मेरा RichTextBox1 (Log.Items.Add (संदेश) है) मैं इसे लॉग करने के लिए नाम दिया है, इसलिए यह पुनः टाइप करना आसान है।

मैं अपडेट लाग (संदेश) को एक अलग रूप से बुला रहा हूं ... हालांकि मुझे यहां अपडेट करें (हालांकि इसमें कोई फर्क नहीं पड़ता है, जहां से मैं अपडेट लॉग (संदेश) को कॉल करता हूं, फिर भी मुझे यह त्रुटि देता है)

आप लोग मेरे लिए चीजों को और अधिक सरल बनाने जा रहे हैं ... और उदाहरण प्रदान करें मैं सब कुछ आप लोग यहाँ कह रहे हैं समझ में नहीं आ रहा है ... मैं तरीकों और हैंडल के साथ काम करने के बारे में कोई सुराग नहीं है मैंने इसके बारे में भी बकवास का शोध किया है ...

दूसरा संपादित करें:

मेरा मानना ​​है कि मैंने इस समस्या का पता लगाया है, लेकिन इसे ठीक करने का तरीका नहीं पता।

मेरे प्रवेश वर्ग में मैं मुख्य कोड बनाने के लिए इस कोड का उपयोग करता हूं:

स्थिर मुख्य मुख्य क्लास = नया मुख्य ();

मैं (पूरी तरह से नया खाका प्रतिलिपि मेन) बना रहा हूं, जिसमें लॉग (रिच टेक्स्टबॉक्स मैं अद्यतन करने का प्रयास कर रहा हूं)

जब मैं updateLog (संदेश) को कॉल करता हूं तो मुझे विश्वास है कि मैं मेन () की दूसरी इकाई पर लॉग (रिचटेक्स्टबॉक्स) अपडेट करने की कोशिश कर रहा हूं जो अन्यथा मुख्य क्लास के रूप में जाना जाता है बेशक, ऐसा करने से मुझे यह अपवाद फेंक दिया जाएगा क्योंकि मैंने यह भी नहीं देखा है कि वर्तमान मेन का प्रतिकृति उपयोग कर रहा हूं।

यह वही है जो मैं शूटिंग कर रहा हूं, उन लोगों में से एक के लिए धन्यवाद जो जवाब देते हैं:

Main mainClass = Application.OpenForms.OfType<Main>().First();
logAddDelegate = mainClass.logAdd; 
logAddDelegate(message);

मुझे नये () ऑपरेटर के साथ मुख्य क्लास बनाने की आवश्यकता नहीं है क्योंकि मैं उस फॉर्म का एक नया खाका बनाना नहीं चाहता जो मैं वर्तमान फॉर्म को संपादित करने में सक्षम होना चाहता हूं।

उपरोक्त कोड यद्यपि काम नहीं करता है, मुझे आवेदन भी नहीं मिल सकता है। क्या यह भी सी # सिंटैक्स है?

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

अंतिम संपादित करें:

मुझे ये समझ में आ गया है कि नीचे दिए गए उपयोगकर्ताओं में से किसी एक के लिए धन्यवाद। यहां मेरा अपडेट कोड है:

मुख्य फ़ॉर्म कोड:

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;
using System.Data.OleDb;
using System.Collections.Specialized;
using System.Text;
using System.Threading;

delegate void logAdd(string message);

namespace LCR_ShepherdStaffupdater_1._0
{
    public partial class Main : Form
    {
        private static Main mainFormForLogging;
        public static Main MainFormForLogging
        {
            get
            {
                return mainFormForLogging;
            }
        }

        public Main()
        {
            InitializeComponent();
            if (mainFormForLogging == null)
            {
                mainFormForLogging = this;
            }
        }

        public void add(string message)
        {
            this.Log.Items.Add(message);
        }
        public void logAdd(string message)
        {
            this.Log.BeginInvoke(new logAdd(add), new object[] { message });
        }

        private void exitProgramToolStripMenuItem_Click(object sender, EventArgs e) 
        {
            Application.Exit(); 
        }
        private void aboutToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            Form aboutBox = new AboutBox1(); 
            aboutBox.ShowDialog(); 
        }

        private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
        {
        }

        private void settingsToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            settingsForm.settings.ShowDialog();
        }

        private void synchronize_Click(object sender, EventArgs e)
        {
            add("test");
            Logging.updateLog("testthisone");
            //DatabaseHandling.createDataSet();
        }

    }

    public class settingsForm 
    {
        public static Form settings = new Settings();
    }

}

लॉगिंग वर्ग कोड:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LCR_ShepherdStaffupdater_1._0
{
    public class Logging
    {

        static Main mainClass = Main.MainFormForLogging;
        static logAdd logAddDelegate;

        public static void updateLog(string message)
        {
            logAddDelegate = mainClass.logAdd;
            logAddDelegate(message);
        }
    }
}

logAddDelegate (संदेश);

मुझे लगता है कि आप इसको कॉल कर रहे हैं इससे पहले कि Form_Load ईवेंट उठाया गया है। लॉग को जोड़ने से पहले लोड करने के लिए फ़ॉर्म को प्रतीक्षा करने के लिए अपना कोड ठीक करें (...) या तो लॉगिंग .updateLog () को कॉल करने से पहले


मैंने पाया कि InvokeRequired विश्वसनीय नहीं है, इसलिए मैं बस का उपयोग करें

if (!this.IsHandleCreated)
{
    this.CreateHandle();
}

यह एक रनटाइम त्रुटि है, एक कंपाइलर त्रुटि नहीं है

अपने फॉर्म, "मेन" को प्रदर्शित करने के लिए (इसलिए एक विंडो संभाल बनाया गया है) इससे पहले कि आप BeginInvoke पर कॉल कर सकते हैं या इसके बारे में पूछ सकते हैं

मैं आमतौर पर इन स्थितियों में क्या करता हूं, यह निर्धारित करने के लिए फॉर्म पर छोड़ दें कि क्या उसे कॉल करने के लिए BeginInvoke या Invoke का उपयोग करना चाहिए। आप यह जांच सकते हैं कि कॉल के साथ InvokeRequired (MSDN जांचें)।

तो शुरुआत करने के लिए, मैं Loggin वर्ग के अपडेट लॉॉग विधि में लॉग ऐडडिलेगेट कॉल से छुटकारा पाता हूं। एक लॉग जोड़ने के लिए फ़ॉर्म में सीधे कॉल करें इस तरह:

public partial class Main : Form
{
    public Main()
    {
        InitializeComponent();
    }

    private delegate void AddNewLogMessageEventHandler(string message);

    public void AddLogMessage(string message)
    {
        object[] args = new object[1];
        args[0] = message;

        if (InvokeRequired)
            BeginInvoke(new AddNewLogMessageEventHandler(AddLog), args);
        else
            Invoke(new AddNewLogMessageEventHandler(AddLog), args);
    }

    private void AddLog(string message)
    {
        this.Log.Items.Add(message);
    }
 }

}

तो आप देख सकते हैं कि फॉर्म स्वयं को निर्धारित करने के प्रभारी है अगर उसे अतुल्यकालिक तरीके से कॉल करने की आवश्यकता होती है या नहीं।

हालांकि, यह अभी भी आपकी रनटाइम त्रुटि ठीक नहीं करेगा, क्योंकि आप इसे प्रदर्शित होने से पहले फ़ॉर्म में कॉल कर रहे हैं। आप यह देख सकते हैं कि क्या फॉर्म के हैंडल रिक्त है या नहीं, और यह कम से कम आपको यह सत्यापित करने की अनुमति देगा कि क्या आप एक वैध फॉर्म से निपटते हैं या नहीं।


यह त्रुटि तब होती है जब आप उस विंडो पर कॉल करते हैं जो अभी तक 'दिखाया नहीं गया' है। क्या आप वाकई लॉगिंग क्लास (विशेष रूप से पहली पंक्ति) में अपने कोड के साथ मुख्य वर्ग का दूसरा उदाहरण नहीं बना रहे हैं? ऐसा हो सकता है कि जिस मुख्य फॉर्म पर आप लॉग ऑन कर रहे हैं वह मुख्य रूप नहीं है जो आप देख रहे हैं। यदि आप जांचना चाहते हैं, तो अपने लॉगिंग कॉल के अंदर कॉल करें "मेन क्लास। दिखाएँ ()" यदि आप मुख्य रूप से पॉप अप की दूसरी प्रति प्राप्त करते हैं, तो समस्या यह है कि आपका प्रवेश वर्ग आपके फॉर्म के सही 'उदाहरण' का संदर्भ नहीं दे रहा है

एक 'खाका' के रूप में कक्षा के बारे में सोचो क्लास का प्रत्येक उदाहरण ('नया' शब्द के साथ बनाया गया) एक और वस्तु है, जो खाका से बनाया गया है। सिर्फ इसलिए कि दो वस्तुओं (इस मामले में, आपके दो मुख्य रूप) एक ही खाका साझा करते हैं, इसका मतलब यह नहीं है कि आप उन्हें एकांतर रूप से उपयोग कर सकते हैं इस मामले में, आपके पास पहले से एक मुख्य फ़ॉर्म है, और आप इसे 'पुन: उपयोग' करना चाहते हैं तुम कोशिश कर सकते हो:

MainClass myMainForm = Application.OpenForms.OfType<MainClass>().First();
logAddDelegate = myMainForm.logAdd; 
logAddDelegate(message);

आपके लॉग फ़ंक्शन के अंदर जो आपके पास वर्तमान में है उसके बजाय अंतर यह है कि आवेदन करने के लिए कॉल। OpenForms.OfType ()। पहले आपके आवेदन में जाएंगे, और वास्तविक मुख्य फॉर्म को पुनः प्राप्त करेंगे जिसे आप देख रहे हैं (तकनीकी तौर पर, इसे पहले उदाहरण प्राप्त होगा) और उस पर अपना अभिवादन करें फार्म, सीधे

उम्मीद है की यह मदद करेगा।


यह किसी भी अन्य व्यक्ति को इस के साथ पकड़ा गया है, के मामले में मदद करने के लिए है। मेरी समस्या: VB.net: "आवेज़ या ब्वॉयइनवोक को तब तक नियंत्रित नहीं किया जा सकता जब तक कि खिड़की का संचालन तब तक नहीं हुआ।" मैंने उस प्रपत्र को बंद कर दिया, जिसमें ईवेंट के लिए एक हैंडलर प्रतिनिधि को अद्यतन करने के लिए बुला रहा है, बिना हेडलर को हटाने के लिए घटना।

मैंने क्या किया: जब मैं फ़ॉर्म बंद करता हूँ, मैंने सभी हैंडलर्स को हटा दिया, और जब मैंने फॉर्म खोला तब उन्हें वापस सौंप दिया। इस समस्या का हल।


मैंने निम्नलिखित विधि का उपयोग करके इसे हल किया है:

private void invokeOnFormThread(MethodInvoker method)
{
    if (IsHandleCreated)
         Invoke(new EventHandler(delegate { method(); }));
    else
        method();
}

Invoke के बजाय invokeOnFormThread कॉल करें यह केवल फार्म के धागे का उपयोग करेगा यदि एक हैंडल पहले से ही बनाया गया है, अन्यथा यह कॉलर के थ्रेड का उपयोग करेगा


जब आपको यह त्रुटि मिलती है, तो इसका लगभग हमेशा मतलब है कि आपने वास्तव में बनाया गया था इससे पहले कि आप किसी नियंत्रण या फ़ॉर्म पर कार्य करने का प्रयास कर चुके हैं।

WinForms में, जीयूआई तत्वों में दो अर्ध-स्वतंत्र जीवन रहता है: स्मृति में कक्षाएं और ऑपरेटिंग सिस्टम में संस्थाओं के रूप में जैसे, एनएटी में एक नियंत्रण को संदर्भित करना संभव है, जो वास्तव में अभी तक बनाया नहीं गया है। "बनाया जा रहा है संभाल" प्रोग्राम को उसके गुणों में हेरफेर करने की अनुमति देने के लिए ओएस द्वारा नियंत्रण के लिए निर्दिष्ट संख्या रखने के लिए संदर्भित करता है

इस स्थिति में, फ़ॉर्म की लोड इवेंट के अंत में एक झंडे सेट करके और केवल उस ध्वज को सेट किए जाने के बाद फ़ॉर्म के नियंत्रण में हेरफेर करने का प्रयास करके अधिकांश त्रुटियों को समाप्त किया जा सकता है।


ठीक है, मैं फिर से शुरू करने जा रहा हूँ।

यह समझने के लिए कि क्या हो रहा है, आपको यह समझना होगा कि कैसे नेट और विंडोज एक दूसरे से संबंधित हैं। .NET विंडोज पर चलती है और कई देशी, एक विंडो की तरह Win32 अवधारणाओं, एक सूची दृश्य, एक एडिट बॉक्स (एक मानक टेक्स्टबॉक्स के लिए Win32 नाम) पर चलती है। इसका अर्थ है कि आपके पास टेक्स्ट बॉक्स या एक प्रपत्र का एक मान्य .NET आवृत्ति हो सकती है, लेकिन उस आइटम (संपादनबॉक्स या विंडो) का अंतर्निहित Windows संस्करण अभी तक नहीं है जब हैंडल कटाई सही है, तो आइटम का विंडोज संस्करण बनाया जाता है।

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

सामान्य तौर पर एक आवेदन चलाने के लिए आवेदन कॉल करना है। अपने स्टार्टअप विधि में चलाएं (नया मुख्य ()), जो आम तौर पर प्रोग्राम कक्षा में होता है और जिसे मेन कहते हैं मुख्य के इस उदाहरण को इंगित करने के लिए आपको अपने लॉगर की आवश्यकता है

प्रपत्र का उदाहरण प्राप्त करने के कई तरीके हैं, प्रत्येक अपनी स्वयं की चेतावनियों के साथ, लेकिन सादगी के लिए आप मुख्य वर्ग से ही उदाहरण का पर्दाफाश कर सकते हैं उदाहरण के लिए:

public partial class Main : Form
{
    private static Main mainFormForLogging;
    public static Main MainFormForLogging
    {
        get
        {
            return mainFormForLogging;
        }
    }

    public Main()
    {
        InitializeComponent();

        if (mainFormForLogging == null)
        {
            mainFormForLogging = this;
        }
    }

    protected void Dispose(bool disposing)
    {
         if (disposing)
         {
             if (this == mainFormForLogging)
             {
                mainFormForLogging = null;
             }
         }

         base.Dispose(disposing);
    }
}