0
我有很多方法互相調用,每個都有一定的任務,其中一些是異步的,都在DOM上操作(因此只有一個線程必須隨時訪問DOM)。延遲代碼執行的最佳方式是什麼?
例如:
object A() {
/*...A() code 1...*/
var res = B();
/*...A() code 2 that uses res...*/
}
object B() {
/*...B code 1...*/
var res1 = C();
/*...B code 2 that uses res1...*/
var res2 = C();
/*...B code 3 that uses res2...*/
}
object C() {
/*...C code 1...*/
if (rnd.NextDouble() < 0.3) { // unpredictable condition
startAsyncStuff();
/*...C code 2 that uses async result above...*/
}
if (rnd.NextDouble() < 0.7) { // unpredictable condition
startOtherAsyncStuff();
/*...C code 3 that might use any/both async results above...*/
}
}
現在讓我們假設我有一個要執行方法A(方法)1000倍儘可能快地(異步方法可以在單獨的線程運行,但所有其他代碼一次只能訪問一個DOM),所以理想情況下,當到達異步調用時,A(),B()和C()的代碼執行暫停,因此可以再次調用A()。
我有兩種方法可以做到這一點。一個是與產量,通過改變所有的方法來迭代器我可以暫停和恢復執行:
struct DeferResult {
public object Result;
public bool Deferred;
}
IEnumerator<DeferResult> A() {
/*...A() code 1...*/
var dres = B();
if (dres.Deferred) yield dres;
/*...A() code 2...*/
}
IEnumerator<DeferResult> B() {
/*...B code 1...*/
var dres1 = C();
if (dres1.Deferred) yield dres1;
/*...B code 2...*/
var dres2 = C();
if (dres2.Deferred) yield dres2;
/*...B code 3...*/
}
IEnumerator<DeferResult> C() {
/*...C code 1...*/
if (rnd.NextDouble() < 0.3) { // unpredictable condition
startAsyncStuff();
yield return new DeferResult { Deferred = true; }
/*...C code 2 that uses async result above...*/
}
if (rnd.NextDouble() < 0.7) { // unpredictable condition
startOtherAsyncStuff();
yield return new DeferResult { Deferred = true; }
/*...C code 3 that might use any/both async results above...*/
}
yield return new DeferResult { Result = someResult(); }
}
void Main() {
var deferredMethods = new List<IEnumerator<DeferResult>>();
for (int i = 0; i < 1000; i++) {
var en = A().GetEnumerator();
if (en.MoveNext())
if (en.Current.Deferred)
deferredMethods.Add(en);
}
// then use events from the async methods so when any is done continue
// running it's enumerator to execute the code until the next async
// operation, or until finished
// once all 1000 iterations are complete call an AllDone() method.
}
這種方法有從迭代器相當一些開銷,而且是更多的代碼密集,然而這一切在一個線程上運行,所以我不需要同步DOM訪問。
另一種方法是使用線程(1000個併發線程是一個壞主意,所以我會實現某種線程池),但這需要同步DOM訪問,這是昂貴的。
有沒有其他方法可以用來在這些條件下推遲代碼執行?推薦的方法是什麼?
我認爲鎖會做到這一點。如果您使用.Net 4.0或其他ThreadPoll,則任務輪詢使用Task Parallel Library中的內部版本。 – 2010-08-10 09:41:11
我同意,但您可能需要考慮設計更改。爲什麼你會想要這個多線程呢?您將序列化訪問DOM,因此一次只有一個線程可以訪問它,並且您失去了線程的好處。 – 2010-08-10 18:30:03