Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 推迟代码执行的最佳方式是什么?_C#_.net_Multithreading_Yield_Deferred Execution - Fatal编程技术网

C# 推迟代码执行的最佳方式是什么?

C# 推迟代码执行的最佳方式是什么?,c#,.net,multithreading,yield,deferred-execution,C#,.net,Multithreading,Yield,Deferred Execution,我有许多方法相互调用,每个方法都有特定的任务,其中一些是异步的,所有这些任务都在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

我有许多方法相互调用,每个方法都有特定的任务,其中一些是异步的,所有这些任务都在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(){
/*…A()代码1*/
var res=B();
/*…使用res*/
}
对象B(){
/*…B代码1*/
var res1=C();
/*…B使用res1的代码2*/
var res2=C();
/*…B使用res2的代码3*/
}
对象C(){
/*…C代码1*/
如果(rnd.NextDouble()<0.3){//不可预测的条件
startAsyncStuff();
/*…使用上述异步结果的C代码2*/
}
如果(rnd.NextDouble()<0.7){//不可预测的条件
startOtherAsyncStuff();
/*…C代码3,可能使用上述任何/两个异步结果*/
}
}
现在让我们假设我有一个方法希望以尽可能快的1000倍的速度执行方法a()(异步方法可以在单独的线程中运行,但是所有其他代码一次只能访问一个DOM),因此理想情况下,当达到异步调用时,a()的代码执行会暂停,因此可以再次调用a()

我可以想出两种方法来做到这一点。一个是使用yield,通过将所有方法更改为迭代器,我可以暂停并恢复执行:

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.
}
struct结果{
公共客体结果;
公共福利推迟;
}
IEnumerator A(){
/*…A()代码1*/
var-dres=B();
如果(延期存款)产生存款准备金;
/*…A()代码2*/
}
IEnumerator B(){
/*…B代码1*/
var dres1=C();
如果(dres1.递延)产生dres1;
/*…B代码2*/
var dres2=C();
如果(dres2.递延)产生dres2;
/*…B代码3*/
}
IEnumerator C(){
/*…C代码1*/
如果(rnd.NextDouble()<0.3){//不可预测的条件
startAsyncStuff();
返回新的延迟结果{Deferred=true;}
/*…使用上述异步结果的C代码2*/
}
如果(rnd.NextDouble()<0.7){//不可预测的条件
startOtherAsyncStuff();
返回新的延迟结果{Deferred=true;}
/*…C代码3,可能使用上述任何/两个异步结果*/
}
返回新的结果{Result=someResult();}
}
void Main(){
var deferredMethods=新列表();
对于(int i=0;i<1000;i++){
var en=A().GetEnumerator();
if(en.MoveNext())
如果(当前延期)
延迟方法。添加(en);
}
//然后使用异步方法中的事件,以便在完成任何操作后继续
//运行枚举器以执行代码,直到下一个异步
//操作,或直到完成
//完成所有1000次迭代后,调用AllDone()方法。
}
  • 这个方法与迭代器相比有相当大的开销,并且代码更密集,但是它都在一个线程上运行,所以我不需要同步DOM访问

  • 另一种方法是使用线程(1000个并发线程是一个坏主意,所以我要实现某种线程池),但这需要同步DOM访问,这代价很高


在这些条件下,有没有其他方法可以用来延迟代码执行?推荐的方法是什么?

正如Karl所建议的,是否需要多线程?我可能会选择多线程的情况,如果

  • DOM访问是随机的,但并不频繁
  • A、B、C中的所有其他代码在时间上都很重要(与DOM访问代码相比)
  • A、B、C中的所有其他代码都可以以线程安全的方式执行,而不执行任何锁定等操作,即如果它们依赖于某个共享状态,那么您也可以同步访问该状态

    现在,在这种情况下,我会考虑使用线程池多次启动,并同步访问DOM。使用线程安全缓存可以降低DOM同步的成本——当然,这取决于某种DOM访问

    我想一把锁就可以了。对于任务轮询,如果使用.NET 4或其他线程读取,则使用内置任务并行库。我同意,但您可能需要考虑设计更改。你为什么想要这个多线程呢?您将序列化对DOM的访问,这样一次只能有一个线程访问它,这样就失去了线程化的好处。