1

Web リンク チェッカー プログラムを作成していて、Interlocked で説明できない動作に遭遇しました。まず、コードの要約版を次に示します。

public class LinkCheckProcessor
{
    private long _remainingLinks;

    public event EventHandler<LinksCheckedEventArgs> AllLinksChecked;

    private void ProcessLinks(List<Link> links)
    {
        foreach (Link link in links)
        {
            ProcessLink(link);
        }
    }

    private void ProcessLink(Link link)
    {
        var linkChecker = new LinkChecker(link);
        linkChecker.LinkChecked += LinkChecked;
        Interlocked.Increment(ref _remainingLinks);
#if DEBUG
        System.Diagnostics.Debug.WriteLine(String.Format("LinkChecker: Checking link '{0}', remaining: {1}", link, Interlocked.Read(ref _remainingLinks)));
#endif
        linkChecker.Check();
    }

    void LinkChecked(object sender, LinkCheckedEventArgs e)
    {
        var linkChecker = (LinkChecker)sender;

        Interlocked.Decrement(ref _remainingLinks);
#if DEBUG
        System.Diagnostics.Debug.WriteLine(String.Format("LinkChecker: Checked link '{0}', remaining: {1}", linkChecker.Link, Interlocked.Read(ref _remainingLinks)));
#endif
        if (Interlocked.Read(ref _remainingLinks) == 0)
        {
            OnAllLinksChecked(new LinksCheckedEventArgs(this.BatchId, this.Web.Url));
        }
    }
}

デバッグ出力に表示されるのは、次のようなものです。

  • LinkChecker: リンク 'http://serverfault.com' をチェックしました。残り: 1
  • LinkChecker: リンク 'http://superuser.com' をチェックしました。残り: 0
  • LinkChecker: リンク 'http://stackoverflow.com' をチェック、残り: -1

_remainingLinks(一部のコード実行で)が負になる理由がわかりません。AllLinksCheckedこれには、イベントの発生が早すぎるという副作用もあります。(ちなみに、上記のコードには、_remainingLinks触れている場所のみが含まれています。)

私は何を間違っていますか?

4

2 に答える 2

3

カウンターが、、、、になり、何度もゼロに達するAllLinksChecked可能性があるため、ロジックは間違いなく間違っています。0->11->00->11->00->11->0

しかし、どうすればカウントがマイナスになるのかわかりません。_remainingLinksこれらはあなたのコードに現れる唯一の場所ですか?


最初の問題は、インクリメント コードを削除し、ループを開始する前にカウントProcessLinkを初期化するだけで修正できます。ProcessLinkslinks.Count

Interlocked.Exchange(ref _remainingLinks, links.Count)`

の実行links中に他のスレッドから引数が書き込まれることはありませんProcessLinksね。

于 2011-05-22T16:36:36.930 に答える
1

私は手足に出て、 がLinkCheckerへの呼び出しに対して複数のイベントを発生させていることを提案しCheck()ます。これがなければ、値がどのようにマイナスになる可能性があるのか​​ わかりません。

于 2011-05-22T16:55:45.050 に答える