2017-07-27 7 views
6

का उपयोग करते हुए अमान्य ऑपरेशन अपवाद, मैं CopyFromScreen विधि का उपयोग कर स्क्रीन को कैप्चर करने के लिए एक एप्लिकेशन लिख रहा हूं, और मैं अपने स्थानीय नेटवर्क पर भेजने के लिए कैप्चर की गई छवि को भी सहेजना चाहता हूं। तो, मैं एक बिटमैप पर कैप्चर की गई स्क्रीन को स्टोर करने की कोशिश कर रहा हूं, और दो थ्रेड पर पहले बिट कैप्चर की गई दूसरी बिटमैप को सहेज रहा हूं।बिटमैप को सहेजते समय और ग्राफिक्स.copyFromScreen समानांतर-वाई

हालांकि, यह InvalidOperationException फेंक रहा है, जो कहता है कि ऑब्जेक्ट वर्तमान में कहीं और उपयोग में है। अपवाद को System.Drawing.dll द्वारा फेंक दिया गया है।
मैंने लॉक करने का प्रयास किया है, और स्क्रीन को सहेजने और कैप्चर करने के लिए अलग-अलग बिटमैप्स का उपयोग कर रहा हूं। मै इसे होने से कैसे रोकू सकता हूँ? प्रासंगिक कोड:

Bitmap ScreenCapture(Rectangle rctBounds) 
{ 
    Bitmap resultImage = new Bitmap(rctBounds.Width, rctBounds.Height); 

    using (Graphics grImage = Graphics.FromImage(resultImage)) 
    { 
     try 
     { 
      grImage.CopyFromScreen(rctBounds.Location, Point.Empty, rctBounds.Size); 
     } 
     catch (System.InvalidOperationException) 
     { 
      return null; 
     } 
    } 
    return resultImage; 
} 

void ImageEncode(Bitmap bmpSharedImage) 
{ 
    // other encoding tasks 
    pictureBox1.Image = bmpSharedImage; 
    try 
    { 
     Bitmap temp = (Bitmap)bmpSharedImage.Clone(); 
     temp.Save("peace.jpeg"); 
    } 
    catch (System.InvalidOperationException) 
    { 
     return; 
    } 
} 

private void button1_Click(object sender, EventArgs e) 
{ 
    timer1.Interval = 30; 
    timer1.Start(); 
} 

Bitmap newImage = null; 

private async void timer1_Tick(object sender, EventArgs e) 
{ 
    //take new screenshot while encoding the old screenshot 

    Task tskCaptureTask = Task.Run(() => 
     { 
      newImage = ScreenCapture(_rctDisplayBounds); 
     }); 
    Task tskEncodeTask = Task.Run(() => 
      { 
       try 
       { 
        ImageEncode((Bitmap)_bmpThreadSharedImage.Clone()); 
       } 
       catch (InvalidOperationException err) 
       { 
        System.Diagnostics.Debug.Write(err.Source); 
       } 
      }); 

    await Task.WhenAll(tskCaptureTask, tskEncodeTask); 

    _bmpThreadSharedImage = newImage; 
} 

img1img2

+1

जहां यह तय करता है कि कुछ उपयोग में है? – BugFinder

+0

मुझे लगता है कि यह '_bmpTreadSharedImage' है जिसे आपने ऊपर दिए गए कोड में शामिल नहीं किया है जो समस्या पैदा कर रहा है? – DavidG

+0

@ बगफाइंडर अपवाद अनचाहे संदेश 'application.Run (new form1())' line.cs में 'लाइन' पर आता है, और 'CopyFromScreen' और 'बिटमैप। सेव' विधियों को हाइलाइट किया गया – Priyank

उत्तर

4

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

public partial class Form1 : Form 
{ 
    private Thread myUIthred; 

    public Form1() 
    { 
     myUIthred = Thread.CurrentThread; 
     InitializeComponent(); 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     Task.Run(() => SomeTask()); 
    } 

    public void SomeTask() // Works Great. 
    { 
     if (Thread.CurrentThread != myUIthred) //Tell the UI thread to invoke me if its not him who is running me. 
     { 
      BeginInvoke(new Action(SomeTask)); 
      return; 
     } 
     var myhandle = System.Drawing.Graphics.FromHwnd(Handle); 
     myhandle.DrawLine(new Pen(Color.Red), 0, 0, 100, 100); 
    } 

} 

मुद्दा है (जैसा कि Spektre गर्भित):

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

    private void button1_Click(object sender, EventArgs e) 
    { 
     Task.Run(() => SomeTask()); 
    } 

    public void SomeTask() //this will result in 'Invalid operation exception.' 
    { 
     var myhandle = System.Drawing.Graphics.FromHwnd(Handle); 
     myhandle.DrawLine(new Pen(Color.Red), 0, 0, 100, 100); 
    } 
} 

आदेश इसे ठीक करने में आप निम्न कार्य करने की जरूरत है। 'BeginInvoke' वास्तव में 'यह है। BginginInvoke' और 'यह' वह फॉर्म है जो यूआई थ्रेड द्वारा बनाया गया था और इसलिए सभी काम करता है।

1

मैं नहीं सी # में कोड तो मैं गलत यहाँ हो सकता है लेकिन मैं आप Windows का उपयोग कर रहे हैं मान ...

किसी भी दृश्य घटकों को एक्सेस करना (जैसे जीडीआई बिटमैप या विंडो ...) WndProc फ़ंक्शन के बाहर सुरक्षित नहीं है। तो यदि आप जीडीआई बिटमैप (डिवाइस संदर्भ के साथ बिटमैप) का उपयोग कर रहे हैं या किसी भी थ्रेड के अंदर अपनी खिड़की से किसी भी दृश्य घटक को प्रतिपादित/एक्सेस कर रहे हैं तो आपकी समस्या है। उसके बाद अपने अनुप्रयोग एक अपवाद फेंक कर सकते हैं में WinAPIके लिए किसी भी कॉल (यहां तक ​​कि ग्राफिक्स से संबंधित नहीं)

तो अपने WndProc समारोह में इस तरह के किसी भी कोड ले जाने की कोशिश। यदि आपके पास इसकी पहुंच नहीं है तो आपकी विंडो की किसी भी घटना का उपयोग करें (जैसे OnTimer या OnIdle)।

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