线程怎么在外部函数中终止自己

fireyan 2008-05-31 09:22:33
我新开了一个线程,调用了本类中的一个函数,这个函数可以终止这个新开的线程,如果是主线程来调用这个函数,没问题,一切很好,但是这个新开的线程自己调用,一到Abort就出错,请指示怎么回事,下附代码:
class Form1
{
Thread t = null; //窗体初始化后会给该线程赋值

public void StopSys(bool isQuit) //该函数为一个普通的终止函数,主线程调用时没问题,如果t来调用,就会出错
{
try
{
running = false;
if (t != null && t.ThreadState != ThreadState.Aborted && t.IsAlive)
{
t.Abort(); // 《---每次当t来调用此函数,运行到这句就会报错
t.Join();
t = null;
}
......
}
.......
}
}
...全文
152 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
fireyan 2008-06-05
  • 打赏
  • 举报
回复
我感觉还是没人直接回答我的问题。我最后只好把程序改了,把那些功能代码再写一遍,写到线程函数里面就OK了。算了,随便散分吧
fireyan 2008-06-03
  • 打赏
  • 举报
回复
当然,try catch我还是会用,我的目的是不让它出现异常啊,并不是要try到它,而是要看怎么改动就不会出现这个异常,貌似是因为资源没释放干净就强行结束线程造成的,但是怎么释放还是没搞清
家鸣 2008-06-03
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 fireyan 的回复:]
当然,try catch我还是会用,我的目的是不让它出现异常啊,并不是要try到它,而是要看怎么改动就不会出现这个异常,貌似是因为资源没释放干净就强行结束线程造成的,但是怎么释放还是没搞清
[/Quote]
要想让它不出现ThreadAbortException异常,那就不应该调用Abort方法. 这不是资源没释放干净就强行结束线程造成的,在线程上调用Abort方法时,系统在此线程中引发 ThreadAbortException 以中止该线程。
结束线程的方法有很多。如设置布尔型线程结束标志,如:

while( blcontinue )
{
//do some thing
}
//结束时置blcontinue=false就可。

KK3K2005 2008-06-03
  • 打赏
  • 举报
回复
关掉和退出有什么区别?

从外面看是关掉
从内部看就是直接退出线程方法
fuadam 2008-06-01
  • 打赏
  • 举报
回复
我这样的关的好像没问题
private void Run(object t)
{
Thread.Sleep(3000);
MessageBox.Show("关闭自己");
((Thread)t).Abort();
}
在Load方法中加入
Thread t = new Thread(this.Run);
t.Start(t);
家鸣 2008-06-01
  • 打赏
  • 举报
回复
当对线程调用Abort方法时,线程本身就会引发ThreadAbortException异常,所以,楼主所说的错误,是预期得到的。
请在线程的方法体内加上异常捕捉就可:


try
{
//方法体
}
catch (ThreadAbortException e)
{
//处理异常
}

fireyan 2008-06-01
  • 打赏
  • 举报
回复

namespace SynUsers
{
public partial class Form1 : Form
{
[DllImport("kernel32")]
private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder val, int size, string filepath);

static int count = 0;
bool minimized = false;
static bool running = false;
SqlConnection msConn;
OdbcConnection myConn;
int reconnectTime, reconnectNum;
FormWindowState currentState = FormWindowState.Normal;
Thread t = null;

private void Form1_Load(object sender, EventArgs e)
{
if (ReadIniFile())
{
this.WindowState = FormWindowState.Minimized;
t = new Thread(Form1.synTwoDatabases);
running = true;
t.Start(this);
}
}

public bool writeToLog(string MSG, bool isWarning)
{
if (count >= 2 && isWarning)
{
StopSys(false);
count = 0;
return false;
}
try
{
ListViewItem listItem = listView1.Items.Add(DateTime.Now.ToString());
listItem.SubItems.Add(MSG);
if ((int)((listView1.Items.Count - 1) / 5) % 2 == 1)
{
listItem.BackColor = Color.Lavender;
}
else
listItem.BackColor = Color.LemonChiffon;
if (isWarning)
{
listItem.ForeColor = Color.Red;
count++;
/*this.Visible = true;
this.WindowState = currentState;
this.Activate();
this.BringToFront();
this.ShowInTaskbar = true;*/
}
else
{
listItem.ForeColor = Color.Black;
}
if (listView1.Items.Count > 100)
{
listView1.Items.RemoveAt(0);
}
listItem.EnsureVisible();
}
catch
{ }
return true;
}

public DataTable doMSQuery(string sql)
{
DataSet ds = new DataSet();
try
{
SqlDataAdapter adp = new SqlDataAdapter(sql, msConn);
adp.Fill(ds);
if (ds.Tables.Count > 0)
return ds.Tables[0];
else
return null;
}
catch
{
writeToLog("无法连接SQL SERVER", true);
return null;
}
}

public DataTable doMYQuery(string sql)
{
DataSet ds = new DataSet();
try
{
OdbcDataAdapter adp = new OdbcDataAdapter(sql, myConn);
adp.Fill(ds);
if (ds.Tables.Count > 0)
return ds.Tables[0];
else
return null;
}
catch
{
writeToLog("无法连接MYSQL", true);
return null;
}
}

public void StopSys(bool isQuit)
{
try
{
running = false;
if (t != null && t.ThreadState != ThreadState.Aborted && t.IsAlive)
{
try
{
t.Abort();
}
catch (Exception e)
{
writeToLog(e.ToString(),false);
}
t.Join();
t = null;
}
if (msConn.State != ConnectionState.Closed)
msConn.Close();
if (myConn.State != ConnectionState.Closed)
myConn.Close();
}
catch
{
writeToLog("系统停止失败,请重启该软件,并确定数据库连接正确!", false);
}
}

public static void synTwoDatabases(object theMe)
{
Form1 me = (Form1)theMe;
while (Form1.running)
{
string sql = "select * from tri_temp order by id";
DataTable msTab = me.doMSQuery(sql);
DataTable myTab = me.doMYQuery(sql);
if (msTab != null && msTab.Rows.Count > 0)
{
try
{
if (me.myConn.State != ConnectionState.Open)
me.myConn.Open();
foreach (DataRow row in msTab.Rows)
{
string sqlPro = "call pro_Ecshop('" + row["actions"].ToString() + "','" + row["username"].ToString() + "','" + row["password"].ToString() + "','" + row["email"].ToString() + "')";
OdbcCommand com = new OdbcCommand(sqlPro, me.myConn);
com.ExecuteNonQuery();
me.doMSQuery("delete from tri_temp where id=" + row[0].ToString());
}
if (me.myConn.State != ConnectionState.Closed)
me.myConn.Close();
}
catch
{
me.writeToLog("连接MYSQL失败!!", true);
}
}
if (myTab != null && myTab.Rows.Count > 0)
{
try
{
if (me.msConn.State != ConnectionState.Open)
me.msConn.Open();
foreach (DataRow row in myTab.Rows)
{
SqlCommand comm = new SqlCommand("pro_Citysoo", me.msConn);
comm.CommandType = CommandType.StoredProcedure;
comm.Parameters.AddWithValue("@action", row["actions"].ToString());
comm.Parameters.AddWithValue("@username", row["username"].ToString());
comm.Parameters.AddWithValue("@password", row["password"].ToString());
comm.Parameters.AddWithValue("@email", row["email"].ToString());
comm.ExecuteNonQuery();
me.doMYQuery("delete from tri_temp where id=" + row[0].ToString());
}
if (me.msConn.State != ConnectionState.Closed)
me.msConn.Close();
}
catch
{
me.writeToLog("连接SQL SERVER失败!!", true);
}
}
Thread.Sleep(3000);
}
}
}
}
fireyan 2008-06-01
  • 打赏
  • 举报
回复
报的错是:
System.Threading.ThreadAbortException:
Thread was being aborted at System.Threading.Thread.AbortInternal()

好吧,我把整个代码都贴上
我首先在class 里面申明了Thread t = null;这个是个全局变量
然后在Form_Load里面写了t = new Thread(Form1.synTwoDatabases);running = true;t.Start(this);传了this的参数过去
synTwoDatabases的申明为public static void synTwoDatabases(object theMe)
在这个函数里面,每当数据库连接失败,都会调用me.writeToLog("连接SQL SERVER失败!!", true);
public bool writeToLog(string MSG, bool isWarning)
{
if (count >= 2 && isWarning)
{
StopSys(false);
count = 0;
return false;
}
。。。。。
}
这里调用的StopSys函数为
public void StopSys(bool isQuit)
{
try
{
running = false;
if (t != null && t.ThreadState != ThreadState.Aborted && t.IsAlive)
{
try
{
t.Abort(); //<<---还是运行到这一句出错,如果是主线程来调用这个就完全没问题
}
catch (Exception e)
{
writeToLog(e.ToString(),false);
}
t.Join();
t = null;
}
...........
}
}
ProjectDD 2008-06-01
  • 打赏
  • 举报
回复
t.Abort();这个方法的行为如何?其后面再写

t.Join();
t=null;
会不会多余?
minioreo 2008-06-01
  • 打赏
  • 举报
回复
下面这段代码好像没问题

namespace killself
{
class Program
{
public Thread t = null;
static void Main(string[] args)
{
Program p = new Program();
p.t = new Thread(new ThreadStart(p.Kill));
p.t.Start();
Console.WriteLine("terminated");
Console.Read();
}

void Kill()
{
if (t != null && t.ThreadState != ThreadState.Aborted && t.IsAlive)
{
t.Abort(); // 《---每次当t来调用此函数,运行到这句就会报错
t.Join();
t = null;
}
}
}
}
fireyan 2008-05-31
  • 打赏
  • 举报
回复
不需要遍历,我只开一个新的线程,我可以很准确的得到那个线程的句柄,就是t,只是t在调用t.Abort时会出错,要怎么解决呢
eagle_2008 2008-05-31
  • 打赏
  • 举报
回复
遍历当前启动的线程 然后把正在活动的线程结束掉
fireyan 2008-05-31
  • 打赏
  • 举报
回复
主要是我只需要新开一个线程就可以了,所以线程池好像意义不大。
回复1,2楼,对的,我就是要把自己关掉。
Alden 2008-05-31
  • 打赏
  • 举报
回复
t调用这个方法吗,要关闭本身吗,考虑是否可以使用线程池进行线程的管理
fuadam 2008-05-31
  • 打赏
  • 举报
回复
你是要自己把自己关掉?

110,533

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧