-7

15 分間隔で 4 つのスレッドを実行するコードです。前回実行したとき、最初の 15 分間は高速にコピーされましたが (6 分間で 20 ファイル)、2 番目の 15 分間ははるかに遅くなりました。これは散発的なものであり、ボトルネックがある場合は、リモート サーバーの帯域幅制限にあることを確認したいと考えています。

編集: 私は最後の実行を監視しており、15:00 と :45 はそれぞれ 8 分未満でコピーされています。:15 は終了しておらず、どちらも :30 がなく、どちらも :45 の少なくとも 10 分前に開始されています。

これが私のコードです:

static void Main(string[] args)
{

    Timer t0 = new Timer((s) =>
    {
        Class myClass0 = new Class();
        myClass0.DownloadFilesByPeriod(taskRunDateTime, 0, cts0.Token);
        Copy0Done.Set();
    }, null, TimeSpan.FromMinutes(20), TimeSpan.FromMilliseconds(-1));

    Timer t1 = new Timer((s) =>
    {
        Class myClass1 = new Class();
        myClass1.DownloadFilesByPeriod(taskRunDateTime, 1, cts1.Token);
        Copy1Done.Set();
    }, null, TimeSpan.FromMinutes(35), TimeSpan.FromMilliseconds(-1));

    Timer t2 = new Timer((s) =>
    {
        Class myClass2 = new Class();
        myClass2.DownloadFilesByPeriod(taskRunDateTime, 2, cts2.Token);
        Copy2Done.Set();
    }, null, TimeSpan.FromMinutes(50), TimeSpan.FromMilliseconds(-1));

    Timer t3 = new Timer((s) =>
    {
        Class myClass3 = new Class();
        myClass3.DownloadFilesByPeriod(taskRunDateTime, 3, cts3.Token);
        Copy3Done.Set();
    }, null, TimeSpan.FromMinutes(65), TimeSpan.FromMilliseconds(-1));

}

public struct FilesStruct
{
    public string RemoteFilePath;
    public string LocalFilePath;
}

Private void DownloadFilesByPeriod(DateTime TaskRunDateTime, int Period, Object obj)
{

    FilesStruct[] Array = GetAllFiles(TaskRunDateTime, Period);
    //Array has 20 files for the specific period.

    using (Session session = new Session())
    {
        // Connect
        session.Open(sessionOptions);
        TransferOperationResult transferResult;
        foreach (FilesStruct u in Array)
        {
            if (session.FileExists(u.RemoteFilePath)) //File exists remotely
            {
                if (!File.Exists(u.LocalFilePath)) //File does not exist locally
                {
                    transferResult = session.GetFiles(u.RemoteFilePath, u.LocalFilePath);
                    transferResult.Check();
                    foreach (TransferEventArgs transfer in transferResult.Transfers)
                    {
                        //Log that File has been transferred
                    }
                }
                else
                {
                    using (StreamWriter w = File.AppendText(Logger._LogName))
                    {
                        //Log that File exists locally
                    }
                }

            }
            else
            {
                using (StreamWriter w = File.AppendText(Logger._LogName))
                {
                    //Log that File exists remotely
                }
            }
            if (token.IsCancellationRequested)
            {
                break;
            }
        }
    }
}
4

2 に答える 2

2

ここで何かが正しくありません。まず、4 つのタイマーを並行して実行するように設定しています。考えてみれば、必要ありません。4 つのスレッドを常に並行して実行する必要はありません。特定の間隔でタスクを開始するだけです。では、いくつのタイマーが必要ですか? 1。

2番目の問題は、なぜTimeSpan.FromMilliseconds(-1)ですか?その目的は何ですか?なぜそこにそれを入れたのか理解できませんが、私はしません。

3 番目の問題は、マルチプログラミングとは関係ありませんが、とにかく指摘しておく必要がありますが、Class毎回新しいインスタンスを作成することです。これは不要です。クラスで、コンストラクターを設定する必要があり、ロジックがクラスのさまざまなメソッドまたはフィールドに何らかの順序でアクセスする必要がある場合に必要です。あなたの場合、やりたいことはメソッドを呼び出すことだけです。したがって、毎回クラスの新しいインスタンスは必要ありません。呼び出しているメソッドを静的にするだけです。

これが私がすることです:

  1. ダウンロードする必要があるファイルを配列 / List<> に保存します。毎回同じことをしていることに気付きませんか?なぜそのために 4 つの異なるバージョンのコードを書くのでしょうか? これは不要です。アイテムを配列に格納し、呼び出しでインデックスを変更するだけです!
  2. おそらく5秒間隔でタイマーをセットアップします。20分/35分/などのマークに達したら、新しいスレッドを生成してタスクを実行します。そうすれば、前のタスクが完了していなくても、新しいタスクを開始できます。
  3. すべてのスレッドが完了する (終了する) まで待ちます。その場合、例外をスローするかどうかを確認し、必要に応じてそれらを処理/ログに記録します。
  4. すべてが完了したら、プログラムを終了します。

ステップ 2 では、.NET 4.5 を使用している場合、新しいasyncキーワードを使用するオプションがあります。ただし、スレッドを手動で使用する場合、顕著な違いはありません。

そして、なぜそんなに遅いのですか...タスクマネージャーを使用してシステムの状態を確認してみませんか? CPU の使用率が高く、実行されていますか、それともネットワーク スループットが他の何かによって占められていますか? そこから自分で簡単に答えを導き出すことができます。

于 2014-05-16T20:25:13.487 に答える
-2

問題は sftp クライアントでした。

コンソール アプリケーションの目的は、list<> をループしてファイルをダウンロードすることでした。私はwinscpを試してみましたが、それはうまくいきましたが、非常に遅かったです。また、sharpSSH もテストしましたが、winscp よりもさらに低速でした。

最終的に、少なくとも私の特定のケースでは、winscp と Sharpssh の両方よりもはるかに高速な ssh.net を使用することになりました。winscp の問題は、終了後に明確な切断方法がなかったことだと思います。ssh.net では、ファイルをダウンロードするたびに接続/切断できましたが、これは winscp ではできませんでした。

于 2014-05-20T14:03:33.050 に答える