System.AccessViolationException发生在TextView.Buffer上 [英] System.AccessViolationException occurs on TextView.Buffer
问题描述
我正在尝试使用Gtk#GUI在C#上每秒显示一行文本. 文本在.txt文件上,每行有4个整数.
I am trying to show some text on C#, one line per second, using Gtk# GUI. the text is on .txt file, and it has 4 integers at every line.
但是当我在DragonFly BSD上编译它时,前一两行完美显示在文本框中,但是程序停止了,并且出现了SIGABRT和SIGSEGV错误.
but when I compiled it at DragonFly BSD, the first one or two lines are showed perfectly on textbox but the program halts, and I've got SIGABRT and SIGSEGV errors.
所以我已经在Windows上编译了相同的代码,并且出现了以下错误:"System.AccessViolationException"之类的异常.
so I've compiled same code at Windows, and it has this error: Exception of 'System.AccessViolationException' or something like that.
我检查了允许不安全的代码",但结果是相同的.
I've checked "Allow unsafe codes", but the result was same.
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");
}
}
代码的其他部分工作正常,但是在这一部分中会发生错误.
The other parts of code works perfectly, but in this part, the error occurs.
如果我删除'async'和"await Task.Delay(1000);",它没有错误,但是我想每秒显示1行.
If I delete 'async' and "await Task.Delay(1000);", it doesn't have error but I want to display it 1 lines per second.
我该如何解决?
推荐答案
Gtk#很有气质,并且在与UI线程(主要线程)混乱的线程中不能很好地工作.另外,您不能从辅助线程更新UI(这对于所有图形工具包都是常见的).
Gtk# is quite temperamental and does not work very well with threads messing with the UI thread (the main one). Also, you cannot update the UI from a secondary thread (this is common for all graphic toolkits).
如果我正确理解了您的问题,则只能使用System.Threading睡眠一秒钟.问题是,如果您这样做了,那么您的应用将在整整一秒钟内都没有响应.
If I understood your problem correctly, you could only just use System.Threading in order to sleep for a second. The problem is, if you did that, your app would be unresponsive for that whole second.
解决方案是主动等待直到一秒钟过去.这比等待一秒钟要精确得多,但我希望它能满足您的需求.
The solution is to actively wait until a second has passed. This is less exact, than waiting for exactly a second, but I hope it will meet your needs.
这是您需要的代码:
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()),在此目的很方便.在等待时间过去的同时,我们可以重复调用此命令以提供响应迅速的用户界面.
Gtk can run an iteration and return (Gtk.Application.RunIteration()), which is handy for the purpose here. We can call repeately that in order to offer a responsive user interface, while we wait for the time to pass.
如果您对如何使用它有疑问,这是完成任务所需的窗口的全部代码.
And here is the whole code for a window doing the task you need, in case you have doubts about how to use it.
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;
}
希望这会有所帮助.
这篇关于System.AccessViolationException发生在TextView.Buffer上的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!