有一個ThreadTimer,每10秒執(zhí)行一次下面的do().
void do()
{
for(i = 0, i < 10000, i++)
{
IAsyncResult removeResult =?this.BeginVoke(地圖刪除圖元);
IAsyncResult insertResult?=?this.BeginVoke(地圖重繪圖元);
this.EndInvoke(removeResult); this.EndInvoke(insertResult);
}
}
?
程序大概運行過程就是這樣。
現(xiàn)在的問題是,在這段代碼執(zhí)行時,地圖就不能執(zhí)行其它操作,而且主界面也會很卡,幾乎損失對其它操作的響應。
請問這是什么原因?要怎么解決呢?
8 回答

POPMUISE
TA貢獻1765條經(jīng)驗 獲得超5個贊
可能重繪的太頻繁了。
1、可以考慮分區(qū)塊重繪
2、ThreadTimer也會造成重入的情況,即第一次還沒完成,第二次又觸發(fā)了。
3、你在主線程代碼中調用了EndInvoke方法,這實際上也導致你整個for循環(huán)是同步執(zhí)行的??梢钥紤]把你整個for里面的代碼放入一個輔助線程中執(zhí)行
4、可以考慮給一個計數(shù)變量,在輔助線程開始時+1,結束時-1.用此變量來限制任務數(shù)量,比如到100時就先讓線程暫定下。注意計數(shù)的自增遞減要用interlocked。。(或則使用信號量來限流Semaphore)
?

慕容3067478
TA貢獻1773條經(jīng)驗 獲得超3個贊
原因很簡單,你在極短的時間內執(zhí)行了20000個UI操作,根據(jù)每個操作的時長,和默認線程池大小,估計能夠達到 100個每秒。
UI是采用的單線程單元模型,建議你按順序執(zhí)行 20000 個操作,不要用多線程來執(zhí)行。

BIG陽
TA貢獻1859條經(jīng)驗 獲得超6個贊
@Selway:?這個場景比較復雜,一是對圖形繪制知識的掌握,還有就是對需求的充分理解。比如,我假設用戶對實時性要求不高,并且地圖重繪圖元操作時間極短,那么可以在一個循環(huán)內去執(zhí)行繪制,并在每10次繪制后調用一次Application.DoEvent(此方法會通知UI線程先去處理下別的UI消息)。還可以在繪制前禁止重繪,然后在所有繪制完成后,再啟用重繪??梢岳秒p緩沖模式來繪制你的圖形。

暮色呼如
TA貢獻1853條經(jīng)驗 獲得超9個贊
@Selway:?我不太了解你的需求,也不知道你的地圖是如何繪制的。因此我能給你的建議是你應該理解Windows窗體程序的消息機制,明白了后,你應該可以找到一個切入點把你的應用優(yōu)化成符合該消息機制的方式來運行。

侃侃無極
TA貢獻2051條經(jīng)驗 獲得超10個贊
那個EndEnvoke方法好像不是那么調用的.應該是放在BeginInvoke的內部..
你試試看,我給你一個學習時的例子,不知道改成這樣有沒有效果.
using System;
using System.Security.Permissions;
using System.Threading;
class ThreadInterrupt
{
//定義一個委托
public delegate void DoSomething();
static void Main(string[] args)
{
//1.實例化一個委托,調用者發(fā)送一個請求,請求執(zhí)行該方法體(還未執(zhí)行)
DoSomething doSomething = new DoSomething(
() =>
{
Console.WriteLine("如果委托使用beginInvoke的話,這里便是異步方法體");
Thread.Sleep(5000);
//4,實現(xiàn)完這個方法體后自動觸發(fā)下面的回調函數(shù)方法體
});
//3 。調用者(主線程)去觸發(fā)異步調用,采用異步的方式請求上面的方法體
IAsyncResult result = doSomething.BeginInvoke(
//2.自定義上面方法體執(zhí)行后的回調函數(shù)
new AsyncCallback
(
//5.以下是回調函數(shù)方法體
//asyncResult.AsyncState其實就是AsyncCallback委托中的第二個參數(shù)
asyncResult =>
{
doSomething.EndInvoke(asyncResult);
Console.WriteLine(asyncResult.AsyncState.ToString()+"XX");
}
)
, "BeginInvoke方法的第二個參數(shù)就是傳入AsyncCallback中的AsyncResult.AsyncState,我們使用時可以強轉成相關類型加以使用");
//DoSomething......調用者(主線程)會去做自己的事情
for(int i=0;i<99999;i++)
{
Console.WriteLine(i);
Thread.Sleep(1000);
}
Console.ReadKey();
}
}
注意EndInvoke的位置,另外,如果同時開2000個線程,如果機器配置不怎么樣的話,肯定會很卡的.
- 8 回答
- 0 關注
- 417 瀏覽
添加回答
舉報
0/150
提交
取消