Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/259.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在Gtk窗口中刷新图像,经过一定时间后图像消失_C#_.net_Gtk# - Fatal编程技术网

C# 在Gtk窗口中刷新图像,经过一定时间后图像消失

C# 在Gtk窗口中刷新图像,经过一定时间后图像消失,c#,.net,gtk#,C#,.net,Gtk#,我正在使用C#、.NET4.5和Gtk编写一个简单的应用程序,它捕获屏幕的一部分并将其加载到窗口中的图像上。几秒钟后,图像消失,出现以下错误: Glib CRITICAL**:尝试删除源ID xxxx时未找到它 相关代码: Program.cs: using System.Windows.Forms; namespace Dota2Trainer { class MainClass { public static void Main(string[] args)

我正在使用C#、.NET4.5和Gtk编写一个简单的应用程序,它捕获屏幕的一部分并将其加载到窗口中的图像上。几秒钟后,图像消失,出现以下错误:

Glib CRITICAL**:尝试删除源ID xxxx时未找到它

相关代码:

Program.cs:

using System.Windows.Forms;

namespace Dota2Trainer
{
    class MainClass
    {
        public static void Main(string[] args)
        {
            Gtk.Application.Init();
            MiniMapOverlay myWin = new MiniMapOverlay();
            myWin.KeepAbove = true;
            //myWin.Decorated = false;
            myWin.Resize(200, 200);
            myWin.ShowAll();
            ScreenCapturer screenCap = new ScreenCapturer(30, Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, myWin);
            screenCap.Start();
            Gtk.Application.Run();
        }
    }
}
using System;
using System.Drawing;
using System.IO;
using System.Timers;
using Gtk;

namespace Dota2Trainer
{
    public partial class MiniMapOverlay : Gtk.Window
    {
        Gtk.Image image = null;
        public MiniMapOverlay() : base(Gtk.WindowType.Toplevel)
        {
            image = new Gtk.Image();
            var buffer = System.IO.File.ReadAllBytes(".\\image0.jpeg");
            var pixbuf = new Gdk.Pixbuf(buffer);
            image.Pixbuf = pixbuf;
            this.Add(image);
            this.Build();
        }

        public void RefreshImage(byte[] buffer)
        {
            try
            {
                var pixbuf = new Gdk.Pixbuf(buffer);
                image.Pixbuf = pixbuf;
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception.Message);
            }
        }
    }
}
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Timers;

namespace Dota2Trainer
{
    public delegate void OnSavedImage(byte[] screenCap);
    public class ScreenCapturer
    {
        public System.Timers.Timer aTimer;
        int interval= 30000;
        readonly int screenWidth;
        readonly int screenHeight;
        Rectangle bounds;
        const double miniMapWidthPercentage = 0.15;
        const double miniMapHeightPercentage = 0.25;
        Bitmap bitmap;
        bool Busy = false;
        ImageConverter converter = new ImageConverter();
        public OnSavedImage onSaveImage;

        public ScreenCapturer(int interval, int screenWidth, int screenHeight, MiniMapOverlay imageHolder)
        {
            this.screenHeight = screenHeight;
            this.screenWidth = screenWidth;
            this.interval = interval;
            aTimer = new System.Timers.Timer();
            aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
            aTimer.Interval = this.interval;
            int miniMapWidth = (int)(screenWidth * miniMapWidthPercentage);
            int miniMapHeight = (int)(screenHeight * miniMapHeightPercentage);
            int miniMapStartWidth = (screenWidth - miniMapWidth);
            int miniMapStartHeight = (screenHeight - miniMapHeight);

            bounds = new Rectangle(miniMapStartWidth, miniMapStartHeight, miniMapWidth, miniMapHeight);
            bitmap = new Bitmap(bounds.Width, bounds.Height);
            onSaveImage += imageHolder.RefreshImage;
        }

        public void Start()
        {
            aTimer.Enabled = true;
        }

        public void OnTimedEvent(object sender, ElapsedEventArgs e)
        {
            try
            {
                if (Busy)
                    return;
                Busy = true;
                using (Graphics g = Graphics.FromImage(bitmap))
                {
                    g.CopyFromScreen(new Point(bounds.Left, bounds.Top), Point.Empty, bounds.Size);
                    onSaveImage((byte[])converter.ConvertTo(bitmap, typeof(byte[])));
                }
                Busy = false;
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception.Message);
            }
        }
    }
}
MiniMapOverlay.cs:

using System.Windows.Forms;

namespace Dota2Trainer
{
    class MainClass
    {
        public static void Main(string[] args)
        {
            Gtk.Application.Init();
            MiniMapOverlay myWin = new MiniMapOverlay();
            myWin.KeepAbove = true;
            //myWin.Decorated = false;
            myWin.Resize(200, 200);
            myWin.ShowAll();
            ScreenCapturer screenCap = new ScreenCapturer(30, Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, myWin);
            screenCap.Start();
            Gtk.Application.Run();
        }
    }
}
using System;
using System.Drawing;
using System.IO;
using System.Timers;
using Gtk;

namespace Dota2Trainer
{
    public partial class MiniMapOverlay : Gtk.Window
    {
        Gtk.Image image = null;
        public MiniMapOverlay() : base(Gtk.WindowType.Toplevel)
        {
            image = new Gtk.Image();
            var buffer = System.IO.File.ReadAllBytes(".\\image0.jpeg");
            var pixbuf = new Gdk.Pixbuf(buffer);
            image.Pixbuf = pixbuf;
            this.Add(image);
            this.Build();
        }

        public void RefreshImage(byte[] buffer)
        {
            try
            {
                var pixbuf = new Gdk.Pixbuf(buffer);
                image.Pixbuf = pixbuf;
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception.Message);
            }
        }
    }
}
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Timers;

namespace Dota2Trainer
{
    public delegate void OnSavedImage(byte[] screenCap);
    public class ScreenCapturer
    {
        public System.Timers.Timer aTimer;
        int interval= 30000;
        readonly int screenWidth;
        readonly int screenHeight;
        Rectangle bounds;
        const double miniMapWidthPercentage = 0.15;
        const double miniMapHeightPercentage = 0.25;
        Bitmap bitmap;
        bool Busy = false;
        ImageConverter converter = new ImageConverter();
        public OnSavedImage onSaveImage;

        public ScreenCapturer(int interval, int screenWidth, int screenHeight, MiniMapOverlay imageHolder)
        {
            this.screenHeight = screenHeight;
            this.screenWidth = screenWidth;
            this.interval = interval;
            aTimer = new System.Timers.Timer();
            aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
            aTimer.Interval = this.interval;
            int miniMapWidth = (int)(screenWidth * miniMapWidthPercentage);
            int miniMapHeight = (int)(screenHeight * miniMapHeightPercentage);
            int miniMapStartWidth = (screenWidth - miniMapWidth);
            int miniMapStartHeight = (screenHeight - miniMapHeight);

            bounds = new Rectangle(miniMapStartWidth, miniMapStartHeight, miniMapWidth, miniMapHeight);
            bitmap = new Bitmap(bounds.Width, bounds.Height);
            onSaveImage += imageHolder.RefreshImage;
        }

        public void Start()
        {
            aTimer.Enabled = true;
        }

        public void OnTimedEvent(object sender, ElapsedEventArgs e)
        {
            try
            {
                if (Busy)
                    return;
                Busy = true;
                using (Graphics g = Graphics.FromImage(bitmap))
                {
                    g.CopyFromScreen(new Point(bounds.Left, bounds.Top), Point.Empty, bounds.Size);
                    onSaveImage((byte[])converter.ConvertTo(bitmap, typeof(byte[])));
                }
                Busy = false;
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception.Message);
            }
        }
    }
}
ScreenCapturer.cs:

using System.Windows.Forms;

namespace Dota2Trainer
{
    class MainClass
    {
        public static void Main(string[] args)
        {
            Gtk.Application.Init();
            MiniMapOverlay myWin = new MiniMapOverlay();
            myWin.KeepAbove = true;
            //myWin.Decorated = false;
            myWin.Resize(200, 200);
            myWin.ShowAll();
            ScreenCapturer screenCap = new ScreenCapturer(30, Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, myWin);
            screenCap.Start();
            Gtk.Application.Run();
        }
    }
}
using System;
using System.Drawing;
using System.IO;
using System.Timers;
using Gtk;

namespace Dota2Trainer
{
    public partial class MiniMapOverlay : Gtk.Window
    {
        Gtk.Image image = null;
        public MiniMapOverlay() : base(Gtk.WindowType.Toplevel)
        {
            image = new Gtk.Image();
            var buffer = System.IO.File.ReadAllBytes(".\\image0.jpeg");
            var pixbuf = new Gdk.Pixbuf(buffer);
            image.Pixbuf = pixbuf;
            this.Add(image);
            this.Build();
        }

        public void RefreshImage(byte[] buffer)
        {
            try
            {
                var pixbuf = new Gdk.Pixbuf(buffer);
                image.Pixbuf = pixbuf;
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception.Message);
            }
        }
    }
}
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Timers;

namespace Dota2Trainer
{
    public delegate void OnSavedImage(byte[] screenCap);
    public class ScreenCapturer
    {
        public System.Timers.Timer aTimer;
        int interval= 30000;
        readonly int screenWidth;
        readonly int screenHeight;
        Rectangle bounds;
        const double miniMapWidthPercentage = 0.15;
        const double miniMapHeightPercentage = 0.25;
        Bitmap bitmap;
        bool Busy = false;
        ImageConverter converter = new ImageConverter();
        public OnSavedImage onSaveImage;

        public ScreenCapturer(int interval, int screenWidth, int screenHeight, MiniMapOverlay imageHolder)
        {
            this.screenHeight = screenHeight;
            this.screenWidth = screenWidth;
            this.interval = interval;
            aTimer = new System.Timers.Timer();
            aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
            aTimer.Interval = this.interval;
            int miniMapWidth = (int)(screenWidth * miniMapWidthPercentage);
            int miniMapHeight = (int)(screenHeight * miniMapHeightPercentage);
            int miniMapStartWidth = (screenWidth - miniMapWidth);
            int miniMapStartHeight = (screenHeight - miniMapHeight);

            bounds = new Rectangle(miniMapStartWidth, miniMapStartHeight, miniMapWidth, miniMapHeight);
            bitmap = new Bitmap(bounds.Width, bounds.Height);
            onSaveImage += imageHolder.RefreshImage;
        }

        public void Start()
        {
            aTimer.Enabled = true;
        }

        public void OnTimedEvent(object sender, ElapsedEventArgs e)
        {
            try
            {
                if (Busy)
                    return;
                Busy = true;
                using (Graphics g = Graphics.FromImage(bitmap))
                {
                    g.CopyFromScreen(new Point(bounds.Left, bounds.Top), Point.Empty, bounds.Size);
                    onSaveImage((byte[])converter.ConvertTo(bitmap, typeof(byte[])));
                }
                Busy = false;
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception.Message);
            }
        }
    }
}
完整的源代码可以在这里找到:

它的工作原理是创建一个计时器,在一定时间后运行Screencapturer类的OnTimedEvent()方法,该类有一个委托,该委托将运行MiniMapOverlay RefreshImage()方法。这段代码目前令人震惊,但我只是想在重构之前建立一个粗略的、现成的版本并运行它


我已经寻找了很久,关于为什么会发生这种情况,有什么建议吗?

你应该使用
Glib.Timeout
而不是
System.Timers
System.Timers
可能存在线程问题,并且计时器事件发生在与GTK应用程序不同的线程上
Glib.Timeout
在GTK主应用程序循环中以一定间隔对事件进行排队,并在同一线程中运行。但是,它不适用于时间敏感函数,因为应用程序循环正在处理其他事件,例如鼠标单击。我见过大约半秒到一秒的延迟,但那是在一台旧计算机上调试时发生的。这似乎不是你的应用程序的问题;仅供将来参考。另外,
Glib.Timeout
将继续调用更新事件,直到返回false

uint timerId;

public void Start(uint interval)
{
    timerId = GLib.Timeout.Add (interval, OnUpdateTimer);
}

protected bool OnUpdateTimer ()
{
    try
    {
        if (Busy)
            return;
        Busy = true;
        using (Graphics g = Graphics.FromImage(bitmap))
        {
            g.CopyFromScreen(new Point(bounds.Left, bounds.Top), Point.Empty, bounds.Size);
            onSaveImage((byte[])converter.ConvertTo(bitmap, typeof(byte[])));
        }
        Busy = false;
    }
    catch (Exception exception)
    {
        Console.WriteLine(exception.Message);
    }
    return true;
}

您应该使用
Glib.Timeout
而不是
System.timer
System.Timers
可能存在线程问题,并且计时器事件发生在与GTK应用程序不同的线程上
Glib.Timeout
在GTK主应用程序循环中以一定间隔对事件进行排队,并在同一线程中运行。但是,它不适用于时间敏感函数,因为应用程序循环正在处理其他事件,例如鼠标单击。我见过大约半秒到一秒的延迟,但那是在一台旧计算机上调试时发生的。这似乎不是你的应用程序的问题;仅供将来参考。另外,
Glib.Timeout
将继续调用更新事件,直到返回false

uint timerId;

public void Start(uint interval)
{
    timerId = GLib.Timeout.Add (interval, OnUpdateTimer);
}

protected bool OnUpdateTimer ()
{
    try
    {
        if (Busy)
            return;
        Busy = true;
        using (Graphics g = Graphics.FromImage(bitmap))
        {
            g.CopyFromScreen(new Point(bounds.Left, bounds.Top), Point.Empty, bounds.Size);
            onSaveImage((byte[])converter.ConvertTo(bitmap, typeof(byte[])));
        }
        Busy = false;
    }
    catch (Exception exception)
    {
        Console.WriteLine(exception.Message);
    }
    return true;
}

我不认为有人会想解析你的整个项目,请发布你的源代码中与此问题相关的部分。项目只包含3个小类,我只是加入了它们的源代码,以消除访问git页面的需要。我不认为有人会想解析你的整个项目,请发布与此问题相关的源代码的相关部分。Project只包含3个小类,我刚刚加入了它们的源代码,以消除访问git页面的需要。我想这可能与线程有关。谢谢只是一个小提示,“if(Busy)return;”部分需要返回bool。我想这可能与线程有关。谢谢请注意,“if(Busy)return;”部分需要返回bool。