C#,Threads,Events和DataGrids / DataSet [英] C#, Threads, Events, and DataGrids/DataSets

查看:52
本文介绍了C#,Threads,Events和DataGrids / DataSet的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从表单中运行一个线程,并且每隔一段时间线程就会引发一个事件以便表单读取。当表单获取事件时,表单会将事件放入数据集并将其显示在表单上的数据网格中。问题是线程将慢慢接管所有处理器时间。在大约8个事件之后,表格甚至不再响应。以下是我的测试代码的内容


// Threa的类和事件
使用系统的


名称空间ThreadTestStuf


public delegate void TestEventHandler(object sender,int count)

公共类TestThread

公共事件TestEventHandler TestEvent
public bool stopRunning = false

public TestThread(

{

public void RunningThread()

int xyz = 0

while(!stopRunning)

xyz + = 1

Console.WriteLine(" Count:" + xyz .ToString())

if(xyz%1000 == 0)

TestEvent(this,xyz)


/>
//调用测试线程的表单

//数据集只有(int count)和(string desc)在i


使用System

使用System.Drawing

使用System.Collections

使用System.ComponentModel

使用System。 Windows.Forms

使用System.Data

使用Sy stem.Threading

使用ThreadTestStuff


命名空间ThreadTes


公共类ThreadTestForm:System.Windows.Forms.For


private ThreadTest.TestSet testSet1

private System.Windows.Forms.DataGrid TestDG

private System.Windows.Forms.Button StartThreadButton

private Thread localThread

private TestThread localTestThread


private System.ComponentModel.Container components = null


public ThreadTestForm(


InitializeComponent()

protected override void Dispose(bool disposing

{

localTestThread.stopRunning = true

localThread.Abort()

if(disposing


if(components) != null)


components.Dispose()

base.Dispose(disposing)

private void InitializeComponent(


this.testSet1 = new ThreadTest.TestSet()

this.TestDG = new System.Windows.Forms.DataGrid()

this.StartThreadButton = new System.Windows.Forms.Button()

((System.ComponentModel.ISupportInitialize)(this。 t estSet1))。BeginInit()

((System.ComponentModel.ISupportInitialize)(this.T estDG))。BeginInit()

this.SuspendLayout()

//

// testSet

//

this.testSet1.DataSetName =" TestSet"

this.testSet1.Locale = new System.Globalization.CultureInfo(" en-US")

//

// TestD

//

this.TestDG.DataMember =""

this.TestDG.DataSource = this.testSet1.TestTable

this.TestDG.HeaderForeColor = System.Drawing.SystemColors.ControlText

this.TestDG.Location = new System.Drawing.Point(16,24)

this.TestDG .Name =" TestDG"

this.TestDG.Size = new System.Drawing.Size(320,144)

this.TestDG.TabIndex = 0
//

// StartThreadButto

//

this.StartThreadButton.Location = new System.Drawing.Point(224,184)

this.StartThreadButton.Name =" StartThreadButton"

this.StartThreadButton.Size = new System.Drawing.Size(120,32)

this.StartThreadButton.TabIndex = 1

this.StartThreadButton.Text =" Start Thread"
this.StartThreadButton.Click + = new System.EventHandler(this.StartThreadButton_Click)

//

// ThreadTestFor

//

this.AutoScaleBaseSize = new System.Drawing.Size(5,13)

this.ClientSize = new System.Drawing.Size(376,253)

this.Controls.Add(this.StartThreadButton)

this.Controls.Add(this.TestDG)

this.Name =" ThreadTestForm"

this.Text =" Thread Test Form"

((System.ComponentModel.ISupportInitialize)(this .t estSet1))。EndInit()

((System.ComponentModel.ISupportInitialize)(this.T estDG))。EndInit()

this.ResumeLayout(false)

#endregio


///< summary

///申请的主要入口点

///< / summary

[STAThread

static void Main()


Application.Run(new ThreadTestForm())

private void EventHappend(对象发送者,int count


localThread .Interrupt()

testSet1.TestTable.AddTestTableRow(count," Hello There")

// MessageBox.Show(localThread.ThreadState.ToString())

private void StartThreadButton_Click(object sender,System.EventArgs e

{

localTestThread = new TestThread();

localTestThread .TestEvent + = new TestEventHandler(this.EventHappend);

localThread = new Thread(new ThreadStart(localTestThread.RunningThread));

localThread.Start();

localThread.IsBackground = true;


}

}

}

任何人都可以帮忙吗?

谢谢,

Dennis Owens

解决方案

Dennis Owens< a ***** **@discussions.microsoft.com>写道:

我试图从一个表单运行一个线程,并且每隔一段时间
该线程将引发一个事件以供表单读取。当表单获取事件时,表单会将事件放入数据集中,并将其显示在表单上的数据网格中。问题是
线程将慢慢占用所有处理器时间。在大约8个事件之后,表格甚至不再响应。这是我的测试代码的内容。




我并不感到惊讶 - 你有一个紧密的循环中的8个线程。这是绑定处理器的b
!然而,你还有一些其他的恶作剧

正在进行......


首先,你在非线程中访问stopRunning-安全的方式。你要
应该声明它是不稳定的,或者在

a锁定中包含对它的任何访问权限。


其次,你应该永远不会从非UI线程更新GUI,因为你现在正在做b $ b。您应该使用Control.Invoke在UI线程上调用委托




第三,为什么要从事件中调用localThread.Interrupt()?

那个时候,你实际上正在运行*你正在尝试的线程
中断!


-

Jon Skeet - < sk *** @ pobox.com>
http://www.pobox.com/~skeet

如果回复小组,请不要给我发邮件


中断只是一个疯狂的猜测,试图阻止它吸收所有的处理器时间。我忘了把它留在那里。该方法中唯一的一行应该是在数据集中添加行。至于你的第二件事,这是导致线程接管的原因。好吧,我会查找Control.Invoke,看看我能搞清楚。我仍然没有看到八个线程,只是形式和测试线程


谢谢Dennis Owen


< blockquote>

stopRunning不需要声明为volatile而且不应该使用

带锁。

本机整数赋值是原子操作以及原生整数

促销(即便如此,最后也不算数)。

没有编译器会优化远离变量的加载

非常重要的循环体(就像循环内部的非内联方法调用一样)。

你不需要为原子的单个变量释放/获取语义

赋值。

使用LOCK访问它将是不必要的性能打击,如果没有

说错误。


我想他错误地解释了Thread.Interrupt的含义,并且你的其余评论是正确的。


-Valery。


请访问我的博客:
http://www.harper.no/valery


" Jon Skeet [C#MVP]" < SK *** @ pobox.com>在消息中写道

新闻:MP ************************ @ msnews.microsoft.c om ...

Dennis Owens< an ******* @ discussion.microsoft.com>写道:

我试图从一个表单运行一个线程,并且每隔一段时间
该线程将引发一个事件以供表单读取。当表单获取事件时,表单会将事件放入数据集中,并将其显示在表单上的数据网格中。问题是
线程将慢慢占用所有处理器时间。在大约8个事件之后,表格甚至不再响应。以下是我的测试代码的内容。



我并不感到惊讶 - 你有一个紧密循环的8个线程。这是接管处理器的必要条件!但是,你还有一些其他的恶作剧......

首先,你是以非线程安全的方式访问stopRunning。你应该声明它是易失性的,或者在锁定中包含对它的任何访问权。

其次,你永远不应该从非UI线程更新GUI,正如你现在正在做的那样。您应该使用Control.Invoke来调用UI线程上的委托。

第三,为什么要从事件中调用localThread.Interrupt()?
那时,你实际上正在*正在尝试中断的线程中运行*

-
Jon Skeet - < sk *** @ pobox.com> ;
http://www.pobox.com/~skeet
如果回复小组,请不要给我发邮件



I am trying to run a thread off of a form, and every once in a while the thread will raise an event for the form to read. When the form gets the event, the form will place the event into a dataset and display it on a datagrid that is on the form. The problem is that the thread will slowly take over all of the processor time. After about 8 events, the form will not even respond anymore. Here is the guts of my test code

// Class and event for Threa
using System

namespace ThreadTestStuf

public delegate void TestEventHandler(object sender,int count)
public class TestThread
public event TestEventHandler TestEvent
public bool stopRunning = false
public TestThread(
{
public void RunningThread()
int xyz = 0
while (!stopRunning)
xyz += 1
Console.WriteLine("Count: " + xyz.ToString())
if (xyz % 1000 == 0)
TestEvent(this,xyz)



// Form that call the test threa
// Data set only has (int count) and (string desc) in i

using System
using System.Drawing
using System.Collections
using System.ComponentModel
using System.Windows.Forms
using System.Data
using System.Threading
using ThreadTestStuff

namespace ThreadTes

public class ThreadTestForm : System.Windows.Forms.For

private ThreadTest.TestSet testSet1
private System.Windows.Forms.DataGrid TestDG
private System.Windows.Forms.Button StartThreadButton
private Thread localThread
private TestThread localTestThread

private System.ComponentModel.Container components = null

public ThreadTestForm(

InitializeComponent()
protected override void Dispose( bool disposing
{
localTestThread.stopRunning = true
localThread.Abort()
if( disposing

if (components != null)

components.Dispose()
base.Dispose( disposing )
private void InitializeComponent(

this.testSet1 = new ThreadTest.TestSet()
this.TestDG = new System.Windows.Forms.DataGrid()
this.StartThreadButton = new System.Windows.Forms.Button()
((System.ComponentModel.ISupportInitialize)(this.t estSet1)).BeginInit()
((System.ComponentModel.ISupportInitialize)(this.T estDG)).BeginInit()
this.SuspendLayout()
//
// testSet
//
this.testSet1.DataSetName = "TestSet"
this.testSet1.Locale = new System.Globalization.CultureInfo("en-US")
//
// TestD
//
this.TestDG.DataMember = ""
this.TestDG.DataSource = this.testSet1.TestTable
this.TestDG.HeaderForeColor = System.Drawing.SystemColors.ControlText
this.TestDG.Location = new System.Drawing.Point(16, 24)
this.TestDG.Name = "TestDG"
this.TestDG.Size = new System.Drawing.Size(320, 144)
this.TestDG.TabIndex = 0
//
// StartThreadButto
//
this.StartThreadButton.Location = new System.Drawing.Point(224, 184)
this.StartThreadButton.Name = "StartThreadButton"
this.StartThreadButton.Size = new System.Drawing.Size(120, 32)
this.StartThreadButton.TabIndex = 1
this.StartThreadButton.Text = "Start Thread"
this.StartThreadButton.Click += new System.EventHandler(this.StartThreadButton_Click)
//
// ThreadTestFor
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13)
this.ClientSize = new System.Drawing.Size(376, 253)
this.Controls.Add(this.StartThreadButton)
this.Controls.Add(this.TestDG)
this.Name = "ThreadTestForm"
this.Text = "Thread Test Form"
((System.ComponentModel.ISupportInitialize)(this.t estSet1)).EndInit()
((System.ComponentModel.ISupportInitialize)(this.T estDG)).EndInit()
this.ResumeLayout(false)
#endregio

/// <summary
/// The main entry point for the application
/// </summary
[STAThread
static void Main()

Application.Run(new ThreadTestForm())

private void EventHappend(object sender, int count

localThread.Interrupt()
testSet1.TestTable.AddTestTableRow(count,"Hello There")
// MessageBox.Show(localThread.ThreadState.ToString() )
private void StartThreadButton_Click(object sender, System.EventArgs e
{
localTestThread = new TestThread();
localTestThread.TestEvent += new TestEventHandler(this.EventHappend);
localThread = new Thread(new ThreadStart(localTestThread.RunningThread));
localThread.Start();
localThread.IsBackground = true;

}
}
}

Can anyone help?
Thanks,
Dennis Owens

解决方案

Dennis Owens <an*******@discussions.microsoft.com> wrote:

I am trying to run a thread off of a form, and every once in a while
the thread will raise an event for the form to read. When the form
gets the event, the form will place the event into a dataset and
display it on a datagrid that is on the form. The problem is that the
thread will slowly take over all of the processor time. After about 8
events, the form will not even respond anymore. Here is the guts of my
test code.



I''m not surprised - you''ve got 8 threads in a tight loop. That''s bound
to take over the processor! However, you''ve got a few other nasties
going on...

Firstly, you''re accessing stopRunning in a non-thread-safe way. You
should either declare it as being volatile, or wrap any access to it in
a lock.

Secondly, you should never update the GUI from a non-UI thread, as you
currently are doing. You should use Control.Invoke to invoke a delegate
on the UI thread.

Thirdly, why are you calling localThread.Interrupt() from your event?
At that time, you''re actually running *in* the thread you''re trying to
interrupt!

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too


The interrrupt was just a wild guess to try and stop it from sucking up all the processor time. I forgot I left it in there. The only line in that method should be the adding of the row in the dataset. As for your second thing, is this what is causing the thread to take over. Well I will lookup Control.Invoke and see if I can figure it out. I still don''t see the eight threads, just the form and the test thread

Thanks Dennis Owen


Hi,
stopRunning doesn''t need to be declared volatile and it should not be used
with locks.
Native integer assignment is atomic operation as well as native integer
promotion (even so the last doesn''t even count).
No compiler would optimize away loading of cycle variable when there is
nontrivial cycle body (like non-inlined method calls inside of cycle).
And you don''t need release/acquire semantic for single variable with atomic
assignment.
Using LOCK for accessing it would be unnecessary performance hit if not to
say a mistake.

I suppose that he misinterpreted meaning of Thread.Interrupt, and you are
correct with the rest of your comments.

-Valery.

See my blog at:
http://www.harper.no/valery

"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...

Dennis Owens <an*******@discussions.microsoft.com> wrote:

I am trying to run a thread off of a form, and every once in a while
the thread will raise an event for the form to read. When the form
gets the event, the form will place the event into a dataset and
display it on a datagrid that is on the form. The problem is that the
thread will slowly take over all of the processor time. After about 8
events, the form will not even respond anymore. Here is the guts of my
test code.



I''m not surprised - you''ve got 8 threads in a tight loop. That''s bound
to take over the processor! However, you''ve got a few other nasties
going on...

Firstly, you''re accessing stopRunning in a non-thread-safe way. You
should either declare it as being volatile, or wrap any access to it in
a lock.

Secondly, you should never update the GUI from a non-UI thread, as you
currently are doing. You should use Control.Invoke to invoke a delegate
on the UI thread.

Thirdly, why are you calling localThread.Interrupt() from your event?
At that time, you''re actually running *in* the thread you''re trying to
interrupt!

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too



这篇关于C#,Threads,Events和DataGrids / DataSet的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆