Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/267.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# 睡眠永远不会回来_C#_Multithreading_Timer_Gtk# - Fatal编程技术网

C# 睡眠永远不会回来

C# 睡眠永远不会回来,c#,multithreading,timer,gtk#,C#,Multithreading,Timer,Gtk#,我有一个应用程序在表单上绘制一些东西(只是一个测试应用程序)。我面临着睡眠问题。我使用每100毫秒启动DrawinArea重新绘制的线程。它工作正常,但有时此线程无法从此.Sleep(100)调用返回。我已经签入了调试器,我确信问题出在Thread.Sleep()中 注意:需要Gtk才能运行 使用系统; 使用Gtk; 利用开罗; 使用系统线程; 使用系统计时器; 公共部分类主窗口:Gtk.Window { 线程重画线程=新线程(重画器); //System.Timers.Timer Timer=

我有一个应用程序在表单上绘制一些东西(只是一个测试应用程序)。我面临着睡眠问题。我使用每100毫秒启动DrawinArea重新绘制的线程。它工作正常,但有时此线程无法从此.Sleep(100)调用返回。我已经签入了调试器,我确信问题出在Thread.Sleep()中

注意:需要Gtk才能运行

使用系统;
使用Gtk;
利用开罗;
使用系统线程;
使用系统计时器;
公共部分类主窗口:Gtk.Window
{
线程重画线程=新线程(重画器);
//System.Timers.Timer Timer=新的System.Timers.Timer();
静态int调用=0;
公共主窗口()
:基本(Gtk.WindowType.Toplevel)
{
Build();
this.drawingara2.ExposeEvent+=OnExpose;
redrawThread.Name=“redrawThread”;
重画线程。开始(此);
/*
计时器。间隔=100;
计时器运行时间+=(发送方,e)=>
{
drawingarea2.QueueDraw();
};
timer.AutoReset=true;
timer.Start()*/
}
受保护的void OnDeleteEvent(对象发送方,DeleteEventArgs a)
{
redrawThread.Abort();
Application.Quit();
a、 RetVal=true;
}
静态空心重绘器(对象wnd){
var区域=(主窗口)wnd;
while(true)
{
睡眠(100);
area.QueueDraw();
}
}
int x=200;
int x_mod=10;
int y=150;
int y_mod=10;
void OnExpose(对象发送方,ExposeEventArgs参数){
变量区域=(绘图区域)发送器;
如果(x+10>=绘图区域2.Allocation.Width | | x-10<0)
x_mod=-x_mod;
如果(y+10>=绘图区域2.Allocation.Height | | | y-10<0)
y_mod=-y_mod;
x+=x_mod;
y+=y_mod;
var ny=数学.Abs(y-绘图区域2.分配.高度);
使用(var ctx=Gdk.cairohelp.Create(area.GdkWindow))
{
ctx.LineWidth=9;
ctx.SetSourceRGB(0.7,0.2,0.0);
弧(x,ny,10,0,2*Math.PI);
ctx.StrokePreserve();
ctx.SetSourceRGB(0.3,0.4,0.6);
ctx.Fill();
ctx.GetTarget().Dispose();
}
}
}

一旦遇到这个问题,我决定切换到System.Timers.Timer,但我也遇到了一个问题。计时器在一段时间后停止触发事件。我搜索了这个问题,发现若并没有对计时器的引用,GC可以破坏它。我的计时器是类成员,所以引用始终存在,但在任何情况下,它都会停止。问题出在哪里?

来自
QueueDraw()的文档

相当于为小部件的整个区域调用Widget.QueueDrawArea

阅读
QueueDrawArea
的文档

使小部件[…]的矩形区域无效。一旦主循环变为空闲(大致在处理当前批事件之后),窗口将接收所有已失效区域联合的Widget.ExposeEvent事件

所发生的情况是,每100毫秒,您就在主窗口的队列上放置另一条消息,而主窗口处理此请求的时间超过100毫秒。由于生成重画请求的速度快于完成重画请求的速度,因此这会淹没队列,一旦队列达到其最大大小,就无法接收新消息,并且会“锁定”

当您声明您通过更新窗口的标题来测试这一点时,更新还需要转到队列才能完成,但是由于队列已满,因此这些标题更改从未显示。睡眠不是挂起的,只是调试方法由于相同的潜在问题而中断


解决方案是调用
QueueDraw()
的频率较低。

来自
QueueDraw()
的文档

相当于为小部件的整个区域调用Widget.QueueDrawArea

阅读
QueueDrawArea
的文档

使小部件[…]的矩形区域无效。一旦主循环变为空闲(大致在处理当前批事件之后),窗口将接收所有已失效区域联合的Widget.ExposeEvent事件

所发生的情况是,每100毫秒,您就在主窗口的队列上放置另一条消息,而主窗口处理此请求的时间超过100毫秒。由于生成重画请求的速度快于完成重画请求的速度,因此这会淹没队列,一旦队列达到其最大大小,就无法接收新消息,并且会“锁定”

当您声明您通过更新窗口的标题来测试这一点时,更新还需要转到队列才能完成,但是由于队列已满,因此这些标题更改从未显示。睡眠不是挂起的,只是调试方法由于相同的潜在问题而中断


解决方案是调用
QueueDraw()
的频率较低。

来自
QueueDraw()
的文档

相当于为小部件的整个区域调用Widget.QueueDrawArea

阅读
QueueDrawArea
的文档

使小部件[…]的矩形区域无效。一旦主循环变为空闲(大致在处理当前批事件之后),窗口将接收所有已失效区域联合的Widget.ExposeEvent事件

所发生的情况是,每100毫秒,您就在主窗口的队列上放置另一条消息,而主窗口处理此请求的时间超过100毫秒。由于生成重画请求的速度快于完成重画请求的速度,因此这会淹没队列,一旦队列达到其最大大小,就无法接收新消息,并且会“锁定”

当你
using System;
using Gtk;
using Cairo;
using System.Threading;
using System.Timers;

public partial class MainWindow: Gtk.Window
{

    Thread redrawThread = new Thread(Redrawer);

    //System.Timers.Timer timer = new System.Timers.Timer();

    static int calls = 0;

    public MainWindow()
        : base(Gtk.WindowType.Toplevel)
    {
        Build();
        this.drawingarea2.ExposeEvent += OnExpose;

        redrawThread.Name = "Redraw Thread";

        redrawThread.Start(this);
        /*
        timer.Interval = 100;
        timer.Elapsed += (sender, e) =>
        {
            drawingarea2.QueueDraw();
        };
        timer.AutoReset = true;
        timer.Start();*/

    }

    protected void OnDeleteEvent(object sender, DeleteEventArgs a)
    {
        redrawThread.Abort();
        Application.Quit();
        a.RetVal = true;
    }


    static void Redrawer(object wnd) {
        var area = (MainWindow)wnd;
        while (true)
        {
            Thread.Sleep(100);
            area.QueueDraw();
        }
    }

    int x = 200;
    int x_mod = 10;
    int y = 150;
    int y_mod = 10;



    void OnExpose(object sender, ExposeEventArgs args) {

        var area = (DrawingArea)sender;

        if (x + 10 >= drawingarea2.Allocation.Width || x - 10 < 0)
            x_mod = -x_mod;

        if (y + 10 >= drawingarea2.Allocation.Height || y - 10 < 0)
            y_mod = -y_mod;

        x += x_mod;
        y += y_mod;

        var ny = Math.Abs(y - drawingarea2.Allocation.Height);

        using (var ctx = Gdk.CairoHelper.Create(area.GdkWindow))
        {


            ctx.LineWidth = 9;
            ctx.SetSourceRGB(0.7, 0.2, 0.0);

            ctx.Arc(x, ny, 10, 0, 2*Math.PI);
            ctx.StrokePreserve();

            ctx.SetSourceRGB(0.3, 0.4, 0.6);
            ctx.Fill();

            ctx.GetTarget().Dispose();
        }


    }

}