-2

プロジェクトをリファクタリングしようとしていますが、現在、アプリケーションのパフォーマンスを向上させる最善の方法を研究しようとしています。

質問 1. スピンロックとインターロック

カウンターを作成するには、どちらの方法がパフォーマンスが優れているか。

Interlocked.increament(ref counter)

または

SpinLock _spinlock = new SpinLock()
bool lockTaken = false;
try
{
    _spinlock.Enter(ref lockTaken);
    counter = counter + 1;                
}
finally
 { 
     if (lockTaken) _spinlock.Exit(false);
 } 

また、 のように別のカウンターをインクリメントする必要がある場合、別のオブジェクトcounter2を宣言する必要がありますか? または別のオブジェクトSpinLockを使用するのに十分ですか?boolean

質問 2. ネストされたタスクまたはより良い置換の処理

このアプリケーションの現在のバージョンでは、タスクを使用し、新しいタスクをそれぞれ配列に追加してから、Task.WaitAll()

多くの調査の結果、使用したParallel.ForEach方がパフォーマンスが向上することがわかりましたが、現在のスレッドの数を制御するにはどうすればよいですか? MaxDegreeOfParallelismパラメータで aを指定できることはわかっていParallelOptionsますが、問題はここにあります。メソッドが実行されるたびにcrawl(url)、別の限られた数のスレッドが作成されるだけです。つまり、MaxDegree10 に設定すると、実行するたびcrawl(url)に別の +10 が作成されます。どうすればこれを防ぐことができますか?Parallel の代わりにセマフォとスレッドを使用する必要がありますか? それとももっと良い方法がありますか?

public void Start() {
    Parallel.Invoke(() => { crawl(url) } );
}


crawl(string url) {
    var response =  getresponse(url);
    Parallel.foreach(response.links, ParallelOption, link => {
        crawl(link);
    });
}

質問 3. すべてのジョブ (およびネストされたジョブ) が終了したときに通知します。

最後の質問は、すべてのジョブがいつ終了したかをどのように理解できるかということです。

4

2 に答える 2

-1

これについては、Microsoft の Reactive Framework を参照することをお勧めします。Crawl次のように関数を記述できます。

public IObservable<Response> Crawl(string url)
{
    return
        from r in Observable.Start(() => GetResponse(url))
        from l in r.Links.ToObservable()
        from r2 in Crawl(l).StartWith(r)
        select r2;
}

それを呼び出すには、これを試してください:

IObservable<Response> crawls = Crawl("www.microsoft.com");

IDisposable subscription =
    crawls
        .Subscribe(
            r => { /* process each response as it arrives */ },
            () => { /* All crawls complete */ });

終わり。すべてのスレッド化を処理します。NuGet "System.Reactive" だけです。

于 2018-08-06T12:40:42.997 に答える