我正在尝试使用Gtk#GUI在C#上每秒显示一行文本。 文本在.txt文件上,每行有4个整数。
但是当我在DragonFly BSD上编译它时,前一两行完美显示在文本框中,但是程序停止了,并且出现了SIGABRT和SIGSEGV错误。
所以我已经在Windows上编译了相同的代码,并且出现了以下错误:'System.AccessViolationException'之类的异常。
我检查了“允许使用不安全的代码”,但结果相同。
async void DisplayText(string FileName)
{
string[] Temp = File.ReadAllLines(FileName);
string[] ScoreBoard = new string[4];
TextIter Ti = textview.Buffer.StartIter;
foreach (string Line in Temp)
{
ScoreBoard = Line.Split('\t');
await Task.Delay(1000);
textview.Buffer.Insert(ref Ti, ScoreBoard[0]);
textview.Buffer.Insert(ref Ti, " | ");
textview.Buffer.Insert(ref Ti, ScoreBoard[1]);
textview.Buffer.Insert(ref Ti, "\t");
textview.Buffer.Insert(ref Ti, ScoreBoard[2]);
textview.Buffer.Insert(ref Ti, " | ");
textview.Buffer.Insert(ref Ti, ScoreBoard[3]);
textview.Buffer.Insert(ref Ti, "\n");
}
}
代码的其他部分工作正常,但是在这一部分中会发生错误。
如果我删除'async'和“ await Task.Delay(1000);”,它没有错误,但是我想每秒显示1行。
我该如何解决?
答案 0 :(得分:0)
Gtk#很有气质,并且在与UI线程(主要线程)混乱的线程中不能很好地工作。另外,您不能从辅助线程更新UI(这对于所有图形工具包都是常见的)。
如果我正确理解了您的问题,则只能使用System.Threading睡眠一秒钟。问题是,如果您这样做了,那么您的应用将在整整一秒钟内都没有响应。
解决方案是主动等待直到一秒钟过去。这比等待一秒钟要精确得多,但我希望它能满足您的需求。
这是您需要的代码:
void ActivelyWaitFor(long targetMillis)
{
var stopWatch = new System.Diagnostics.Stopwatch();
stopWatch.Start();
while( stopWatch.ElapsedMilliseconds < targetMillis ) {
Gtk.Application.RunIteration();
}
stopWatch.Stop();
}
Gtk可以运行迭代并返回(Gtk.Application.RunIteration()),在此目的很方便。在等待时间过去的同时,我们可以重复调用此命令以提供响应迅速的用户界面。
如果您对如何使用它有疑问,这是完成所需任务的窗口的全部代码。
public class MainWindow: Gtk.Window
{
public MainWindow()
:base(Gtk.WindowType.Toplevel)
{
this.Build();
this.DeleteEvent += (o, evt) => Gtk.Application.Quit();
this.Shown += (o, args) => this.DisplayText();
}
void Build()
{
this.TextView = new Gtk.TextView();
this.Add( this.TextView );
}
void DisplayText()
{
string[] ScoreBoard = new string[4];
Gtk.TextIter Ti = this.TextView.Buffer.StartIter;
string[] Temp = {
"1\t2\t3\t4",
"1\t2\t3\t4",
"1\t2\t3\t4",
"1\t2\t3\t4",
"1\t2\t3\t4",
"1\t2\t3\t4",
};
foreach (string Line in Temp)
{
ScoreBoard = Line.Split('\t');
this.ActivelyWaitFor( 1000 );
this.TextView.Buffer.Insert(ref Ti, ScoreBoard[0]);
this.TextView.Buffer.Insert(ref Ti, " | ");
this.TextView.Buffer.Insert(ref Ti, ScoreBoard[1]);
this.TextView.Buffer.Insert(ref Ti, "\t");
this.TextView.Buffer.Insert(ref Ti, ScoreBoard[2]);
this.TextView.Buffer.Insert(ref Ti, " | ");
this.TextView.Buffer.Insert(ref Ti, ScoreBoard[3]);
this.TextView.Buffer.Insert(ref Ti, "\n");
}
}
void ActivelyWaitFor(long targetMillis)
{
var stopWatch = new System.Diagnostics.Stopwatch();
stopWatch.Start();
while( stopWatch.ElapsedMilliseconds < targetMillis ) {
Gtk.Application.RunIteration();
}
stopWatch.Stop();
}
private Gtk.TextView TextView;
}
希望这会有所帮助。