我點擊按鈕,開一個執行緒(傳參),執行緒方法體是一個回圈,執行緒結束后,繼續點擊按鈕重開執行緒。
執行緒跑著發現我傳的參是之前的引數(前面跑的引數是正常的,中間偶發引數改變)。
請問這是什么原因造成的。
uj5u.com熱心網友回復:
1.你是怎么判斷執行緒結束了2.有可能是你前一個執行緒未結束 所以 中間的時候會有兩個執行緒在傳參
uj5u.com熱心網友回復:
請問你是怎麼結束線程的uj5u.com熱心網友回復:
我方法體是一個回圈,回圈退出了,代碼執行完執行緒就退出了吧
然后我才點擊按鈕新開執行緒的
uj5u.com熱心網友回復:
我方法體里面有執行標志,為true時我break回圈,然后退出
uj5u.com熱心網友回復:
bool a1 = true;private void Form7_Load(object sender, EventArgs e)
{
while (a1)
{
Thread thred = new Thread(too);
thred.Start(); //啟動執行緒
thred.IsBackground=true;
}
如這樣。當我們想停止就直接讓a1為false可以了
uj5u.com熱心網友回復:
代碼呢,截圖看看
uj5u.com熱心網友回復:
1.你是怎么判斷執行緒結束了
2.有可能是你前一個執行緒未結束 所以 中間的時候會有兩個執行緒在傳參
我方法體是一個回圈,回圈退出了,代碼執行完執行緒就退出了吧
然后我才點擊按鈕新開執行緒的
就是這個時機 你能確定在你再次點擊按鈕的時候上一個執行緒已經結束了嗎 如果不能可能是我說的第二點引起的這個現象
uj5u.com熱心網友回復:
1.你是怎么判斷執行緒結束了
2.有可能是你前一個執行緒未結束 所以 中間的時候會有兩個執行緒在傳參
我方法體是一個回圈,回圈退出了,代碼執行完執行緒就退出了吧
然后我才點擊按鈕新開執行緒的
就是這個時機 你能確定在你再次點擊按鈕的時候上一個執行緒已經結束了嗎 如果不能可能是我說的第二點引起的這個現象
那有沒什么辦法避免執行緒重復
uj5u.com熱心網友回復:
添加標志位 比如為true的時候 彈提示框執行緒沒結束 為false的時候 點擊按鈕正常啟動執行緒 在執行緒開始置true 在結束置falseuj5u.com熱心網友回復:
請問你是怎麼結束線程的
我方法體里面有執行標志,為true時我break回圈,然后退出
代碼呢,截圖看看
ClassName cm = new ClassName();
cm.Name = fileName;
if (isUseCamer)
{
QueryDataForMS qdf = new QueryDataForMS();
GetMarkParams(qdf, fileNo);
}
Thread tMain = new Thread(new ParameterizedThreadStart(RunForPrint));
tMain.IsBackground = true;
tMain.Start(cm);
private void RunForPrint(object str)
{
if (str is ClassName)
{
ClassName cmT = (ClassName)str;
if (connectMLCb.Checked)
{
isRun = true;
while (!alarmFlag)
{
if (!connectMLCb.Checked)
{
break;
}
DateTime startTime = DateTime.Now;
DateTime endTime;
string txtPrintCount = GetTbPrintCountText();
string txtNudPrePrintCount = GetNudPrePrintCountText();
int tIntPrintCount = Convert.ToInt32(txtPrintCount);
int tIntNudPrePrintCount = Convert.ToInt32(txtNudPrePrintCount);
if (tIntNudPrePrintCount <= tIntPrintCount)
{
tIntPrintCount -= tIntNudPrePrintCount;
printCountSum = 0;
}
if (loadedFlag)
{
break;
}
do
{
Thread.Sleep(50);
} while (!loaded);
if (catchFlag)
{
break;
}
if (!RunForMachine1(cmT.Name))
{ break; }
if (alarmFlag)
{
break;
}
Thread tThread = new Thread(new ThreadStart(HandDoWork));
tThread.IsBackground = true;
tThread.Start();
do
{
Thread.Sleep(50);
} while (!updownOver);
updownOver = false;
endTime = DateTime.Now;
int timeCount = (endTime - startTime).Minutes * 60 + (endTime - startTime).Seconds;
timeShowTb.Invoke((Action)delegate
{
timeShowTb.Text = timeCount.ToString();
});
Thread countThread = new Thread(new ThreadStart(ThreadCount));
countThread.IsBackground = true;
countThread.Start();
printCountSum += 1;
tbPrintCount.Invoke((Action)delegate
{
tbPrintCount.Text = printCountSum.ToString();
});
if (tIntNudPrePrintCount == printCountSum)
{
printCountFlag = true;
break;
}
}
isRun = false;
}
}
}
代碼有點多
uj5u.com熱心網友回復:
添加標志位 比如為true的時候 彈提示框執行緒沒結束 為false的時候 點擊按鈕正常啟動執行緒 在執行緒開始置true 在結束置false
我有加標志位判斷,但是我開執行緒時那個標志位是false的
uj5u.com熱心網友回復:
把你的方法貼出來。1 我們先確定,你是怎么傳遞這個引數的,是直接執行緒方法內部呼叫外部變數,還是執行緒方法接收的入參
2 我們在確定,你傳遞的是參考型別還是值型別
uj5u.com熱心網友回復:
if(!isRun ){
Thread tMain = new Thread(new ParameterizedThreadStart(RunForPrint));
tMain.IsBackground = true;
tMain.Start(cm);
}
看了一下 你執行緒內部是有標志位 但是沒看見你用到這個isRun 在啟動執行緒的時候判斷一下 為false的時候再啟動執行緒
uj5u.com熱心網友回復:
把你的方法貼出來。
1 我們先確定,你是怎么傳遞這個引數的,是直接執行緒方法內部呼叫外部變數,還是執行緒方法接收的入參
2 我們在確定,你傳遞的是參考型別還是值型別
private void startBtn_Click(object sender, EventArgs e)
{
RecoderLog("點擊了啟動按鈕");
if (!CheckStatus())
{
return;
}
Run();
}
private void Run()
{
if (isRun)
{
return;
}
if (runFlag == 0)
{
return;
}
if (alarmFlag)
{
return;
}
string fileNo = fileName;
if (string.IsNullOrEmpty(fileNo))
{
return;
}
ClassName cm = new ClassName();
cm.Name = fileName;
if (isUseCamer)
{
QueryDataForMS qdf = new QueryDataForMS();
GetMarkParams(qdf, fileNo);
}
Thread tMain = new Thread(new ParameterizedThreadStart(RunForPrint));
tMain.IsBackground = true;
tMain.Start(cm);
}
}
private void RunForPrint(object str)
{
if (str is ClassName)
{
ClassName cmT = (ClassName)str;
if (connectMLCb.Checked)
{
isRun = true;
while (!alarmFlag)
{
if (!connectMLCb.Checked)
{
break;
}
DateTime startTime = DateTime.Now;
DateTime endTime;
string txtPrintCount = GetTbPrintCountText();
string txtNudPrePrintCount = GetNudPrePrintCountText();
int tIntPrintCount = Convert.ToInt32(txtPrintCount);
int tIntNudPrePrintCount = Convert.ToInt32(txtNudPrePrintCount);
if (tIntNudPrePrintCount <= tIntPrintCount)
{
tIntPrintCount -= tIntNudPrePrintCount;
printCountSum = 0;
}
if (loadedFlag)
{
break;
}
do
{
Thread.Sleep(50);
} while (!loaded);
if (catchFlag)
{
break;
}
if (!RunForMachine1(cmT.Name))
{ break; }
if (alarmFlag)
{
break;
}
Thread tThread = new Thread(new ThreadStart(HandDoWork));
tThread.IsBackground = true;
tThread.Start();
do
{
Thread.Sleep(50);
} while (!updownOver);
updownOver = false;
endTime = DateTime.Now;
int timeCount = (endTime - startTime).Minutes * 60 + (endTime - startTime).Seconds;
timeShowTb.Invoke((Action)delegate
{
timeShowTb.Text = timeCount.ToString();
});
Thread countThread = new Thread(new ThreadStart(ThreadCount));
countThread.IsBackground = true;
countThread.Start();
printCountSum += 1;
tbPrintCount.Invoke((Action)delegate
{
tbPrintCount.Text = printCountSum.ToString();
});
if (tIntNudPrePrintCount == printCountSum)
{
printCountFlag = true;
break;
}
}
isRun = false;
}
}
}
之前是傳值型別,我后來改成傳參考型別了。還是有問題
uj5u.com熱心網友回復:
if(!isRun )
{
Thread tMain = new Thread(new ParameterizedThreadStart(RunForPrint));
tMain.IsBackground = true;
tMain.Start(cm);
}
看了一下 你執行緒內部是有標志位 但是沒看見你用到這個isRun 在啟動執行緒的時候判斷一下 為false的時候再啟動執行緒
我開了執行緒后判斷的,代碼貼出來了
uj5u.com熱心網友回復:
if (alarmFlag){
break;
}
你這個只是退出循環罷了,根本沒有停止執行緒的啊。
你應該這樣 Thread tMain;全域變量
bool loadedFlag=true;全域變量
再次點擊按鈕事件
if (loadedFlag)
{
tMain = null;
}
tMain = new Thread(new ParameterizedThreadStart(RunForPrint));
tMain.IsBackground = true;
tMain.Start(cm);
public void RunForPrint()
{
while (!loadedFlag)
{
if (!connectMLCb.Checked)
{
loadedFlag=true;
}
//等等
//thred = null;
}
}
uj5u.com熱心網友回復:
if (alarmFlag)
{
break;
}
你這個只是退出循環罷了,根本沒有停止執行緒的啊。
你應該這樣 Thread tMain;全域變量
bool loadedFlag=true;全域變量
再次點擊按鈕事件
if (loadedFlag)
{
tMain = null;
}
tMain = new Thread(new ParameterizedThreadStart(RunForPrint));
tMain.IsBackground = true;
tMain.Start(cm);
public void RunForPrint()
{
while (!loadedFlag)
{
if (!connectMLCb.Checked)
{
loadedFlag=true;
}
//等等
//thred = null;
}
}
回圈退出,方法體結束。執行緒不是會退出了嗎
uj5u.com熱心網友回復:
一樣的問題https://bbs.csdn.net/topics/392748710
“別和陌生人說話”---------------否則風險自負。
所謂別和陌生人說話的概念-------一個方法就只改用別人傳遞給他的,他自己內部的,他自己創建的
別人傳遞給他的------------當引數傳的
他自己內部的----------比如你上個帖子,人家建議你的,從新封裝一個物件,你要起什么執行緒,在這個物件里玩。
他自己創建的-------------------他自己內部new的物件
你非要跨越-------非要說呼叫外面的一個引數-----------既然是呼叫外面的引數。那么外面可不管你,外面那些東西可不是執行緒安全的
uj5u.com熱心網友回復:
所以,你開執行緒,傳遞一個公用物件,執行緒在開執行緒,而且里面還依賴一大堆公用物件所以最終就是碰運氣,期盼人家沒改
新物件 xx=new 新物件
新物件.xxxxxx=你想傳達的東西
xx.方法1=>{這個物件的這個方法在來,此時每次都是new的新物件,他跟別人沒關系,他不依賴外面}
uj5u.com熱心網友回復:
參見:https://blog.csdn.net/rocklee/article/details/78423505uj5u.com熱心網友回復:
所以,你開執行緒,傳遞一個公用物件,執行緒在開執行緒,而且里面還依賴一大堆公用物件
所以最終就是碰運氣,期盼人家沒改
新物件 xx=new 新物件
新物件.xxxxxx=你想傳達的東西
xx.方法1=>{這個物件的這個方法在來,此時每次都是new的新物件,他跟別人沒關系,他不依賴外面}
我在里面建了一個物件,
private void RunForPrint(object str)
{
if (str is ClassName)
{
ClassName cmT = (ClassName)str;
這樣都會被污染嗎
uj5u.com熱心網友回復:
學習了,謝謝樓主uj5u.com熱心網友回復:
基于SSM框架的論壇怎么實作uj5u.com熱心網友回復:
看的一臉懵逼
uj5u.com熱心網友回復:
不要用thread,thread不太容易判斷執行緒什么時候結束,用backgroundworker或者task就方便許多。uj5u.com熱心網友回復:
用task比較簡單,判斷task狀態就行uj5u.com熱心網友回復:
現在兩個疑點:1.不知道是否多開了執行緒。2.傳進去的引數是不是中途出了問題uj5u.com熱心網友回復:
不錯,不錯,不錯,不錯uj5u.com熱心網友回復:
不錯,不錯,不錯,不錯uj5u.com熱心網友回復:
加個斷點除錯吧老兄uj5u.com熱心網友回復:
進來學習一下,謝謝樓主uj5u.com熱心網友回復:
暈,你的回圈只是不斷的生成新的執行緒而已,哪有退出?uj5u.com熱心網友回復:
你的代碼,混寫了一大堆的東西,我們也不知道你想干嘛,然后到底哪里是你說的“什么東西修改了,偶爾是以前的”我想問一下,你到底想干的是什么,那東西是要同步,還是異步。同時你愿意接受執行緒這種老語法,還是愿意接受task,async/wait這類新語法。
然后我們在來說后面的
uj5u.com熱心網友回復:
如果你愿意接受新語法,這東西很簡單我現在就可以手寫demo(偽代碼)async button_Click()
{
引數物件封裝 xx=new 引數物件封裝()
await 處理(xx)
}
async task 處理( 引數物件封裝 xx)
{
//這里你可以放鎖控制,當然你到底想怎么弄我們不知道到,所以不給你東西,因為這種東西選擇很多,需要考慮是同步/異步,用鎖還是用信號量,并行的還是互斥的
//這里放你前面那一大串東西
var res= await xxxxxxxxx(另一個引數) //這里是號稱的另一個需要很長時間處理的東西
//后面接著做你需要的什么更新UI那一堆操作
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/138591.html
標籤:C#
