У меня есть приложение, которое рисует что-то на форме (просто тестовое приложение). У меня возникла проблема с Thread.Sleep. Я использую thread, который инициирует рисование DrawinArea каждые 100 миллисекунд. Он работает нормально, но иногда этот поток не может вернуться из вызова This.Sleep (100). Я проверил в отладчике, и я уверен, что проблема в Thread.Sleep().Thread.Sleep никогда не возвращает
Внимание: для этого требуется Gtk #.
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();
}
}
}
После того, как столкнулся с этой проблемой, я решил переключиться на System.Timers.Timer, но я также столкнулся с проблемой с ним. Таймер останавливает событие зажигания через некоторое время. Я искал эту проблему и обнаружил, что GC может уничтожить таймер, если нет ссылок на него. Мой таймер является членом класса, поэтому ссылка всегда существует, но в любом случае она останавливается. В чем проблема?
Я не могу придумать ни одной вещи, которую может сделать GTK #, которая предотвратит возврат вызова «Thread.Sleep». Вы сказали, что уверены, что это вызов сна, как * конкретно * вы использовали отладчик, чтобы найти это? –
Во-первых, никогда не используйте 'thread.Sleep' для потоков пользовательского интерфейса. Как вы упомянули в вопросе, перейдите на маршрут * timer * и задайте свою проблему. –
@ L.B Thread.Sleep не используется в потоке пользовательского интерфейса, он используется параллельно, что делает UI для перерисовки. Пользовательский интерфейс всегда отзывчивый в моем случае. – Xanx