2

私の問題は、負荷が増加した場合のaspx.net4.0Webサーバーのブロックに関連しています。ブロックとは、リクエストがクライアントによって送信されたが、応答が約45秒後に返されることを意味します。これは、開発および実稼働環境で再現可能です。この45秒は一定のようで、Constructor()との呼び出しの間のクライアントとaspxページの両方でこれを測定しましたvoid Render(HtmlTextWriter writer)SqlCommand.BeginExecuteReader(...)私は、いくつかのSqlDataSourceと、1ページで合計6つを利用するカスタムメイドのコントロールの両方を使用しています。BeginExecuteReader/EndExecuteReaderパターンでコントロールを非アクティブ化すると、問題を解決できます。したがって、スレッドがThreadPoolで使用可能になるまで、最終的にBeginExecute呼び出しの1つがブロックされると想定します。

デバッグメッセージを出力し、ブロックされた要求が返される直前に常に一連のスレッド終了メッセージが出力されるパターンを認識しました。

スレッド'GetMolFileAsync'(0x1ba4)がコード0(0x0)で終了しました。

スレッド'GetMolFileAsync'(0x27d0)がコード0(0x0)で終了しました。

スレッド''(0x23c)がコード0(0x0)で終了しました。

スレッド'GetCompoundDepositionInfo'(0x1e88)がコード0(0x0)で終了しました。

スレッド'GetMolFileAsync'(0x2758)がコード0(0x0)で終了しました。

0x43 27/07/2012 15:09:4245==>ブロックされたスレッドは45秒かかりました

0x5F 27/07/2012 15:10:27 0 ==>通常の動作、数ミリ秒で処理

..。

これは、データベースへのリクエストを開始する方法です。

public static IAsyncResult GetCompoundDepositionInfoAsync(object sender, EventArgs e, AsyncCallback callback, object state)
    {
        GetCompoundVersionInfoAsyncParameters parameters = (GetCompoundVersionInfoAsyncParameters)state;
        IAsyncResult res = null;

        parameters.cmd = new System.Data.SqlClient.SqlCommand("www.GetCompoundDepositionInfo", new System.Data.SqlClient.SqlConnection(parameters.connectionstring));
        parameters.cmd.CommandType = System.Data.CommandType.StoredProcedure;
        parameters.cmd.Parameters.AddWithValue("@CompoundID", parameters.CompoundID);
        try
        {
            parameters.cmd.Connection.Open();
            res = parameters.cmd.BeginExecuteReader(callback, parameters, System.Data.CommandBehavior.CloseConnection);
        }
        catch (Exception ex)
        {
            if (parameters.cmd.Connection.State == System.Data.ConnectionState.Open)
            {
                parameters.cmd.Connection.Close();
            }
            throw new Exception("Exception in calling GetCompoundDepositionInfoAsync()", ex);
        }
        return res;
    }

これはコールバック関数です

public void GetCompoundDepositionInfoCallback(IAsyncResult result)
    {
        gmdTools.GmdCompound.GetCompoundVersionInfoAsyncParameters param = (gmdTools.GmdCompound.GetCompoundVersionInfoAsyncParameters)result.AsyncState;

        System.Threading.Thread.CurrentThread.Name = "GetCompoundDepositionInfo";
        using(System.Data.SqlClient.SqlCommand command = param.cmd)
        using(System.Data.SqlClient.SqlDataReader reader = command.EndExecuteReader(result))
        {
            try
            {
                if (reader.Read())
                {
                    lblDeposited.Text = string.Concat("at ", reader.GetDateTime(0).ToShortDateString(), " by ", reader.GetString(1));
                }
            }
            finally
            {
                if (reader != null)
                {
                    reader.Close();
                    command.Connection.Close();
                }
            }
        }
    }

そしてこれはそれらを一緒に接着するためのコードです...

Page.RegisterAsyncTask(new PageAsyncTask(
                new BeginEventHandler(gmdTools.GmdCompound.GetCompoundLastChangeInfoAsync)
                , new EndEventHandler(GetCompoundLastChangeInfoCallback)
                , new EndEventHandler(GetCompoundInfoAsyncTimeout)
                , new gmdTools.GmdCompound.GetCompoundVersionInfoAsyncParameters()
                {
                    connectionstring = Properties.Settings.Default.GmdConnectionString,
                    CompoundID = CompoundId,
                }, true
            ));

私はすでにこのコードを見て何時間も費やしたので、フィードバックをいただければ幸いです。

UPDATE この45秒はデフォルトで推論され、ステートメントPage.AsyncTimeoutを使用して10秒に変更できます。Async="true" AsyncTimeout="10"適切なインデックスを追加することでサイトの全体的なパフォーマンスを大幅に向上させましたが、サーバーが応答を送信する前に、クライアントがこの時間待機しなければならない場合があります。この場合、AsyncTimeoutハンドラーは呼び出されません。ページはすべての非同期操作を登録していると思いますが、最終的には一部の非同期操作が正常に完了したことを認識しないため、ページをレンダリングする前にAsyncTimeout秒待機します。それについて何かコメントはありますか?

4

2 に答える 2

0

おそらくデータベースは、クエリが返す選択肢または行を考えると、1000分の1より多いか少ないかを選択していますか?MS SQLは、返される1000行に1つを選択すると、動作方法が変わります。SQLプロファイラーを使用してクエリを実行すると、テーブルスキャンが実行されますか?欠落しているインデックスを判別するために組み込みのspを実行すると、これらのテーブルのインデックスに対する要求が返されますか?あなたの統計は最新ですか?これの手がかりは、バックアップを復元すると統計が更新されるため、復元されたバックアップはクエリをすばやく実行することです。すべてのテーブルにクラスター化インデックスがありますか?

また、この回答は、関連するEntityFrameworkMVCの遅いページの読み込みに関連している可能性があります

于 2012-07-27T16:59:37.617 に答える
0

connectionstringでasync=trueプロパティを使用していますか。これは、SqlClientを使用した実際の非同期操作に必要です。可能であれば、以下のようなコードでタスク非同期機能を使用して.Net4.5でこれを試すことができます。

public async Task GetCompoundDepositionInfoAsync(CancellationToken cancellationToken)
{
    parameters.cmd = new System.Data.SqlClient.SqlCommand("www.GetCompoundDepositionInfo", new System.Data.SqlClient.SqlConnection(parameters.connectionstring));
    parameters.cmd.CommandType = System.Data.CommandType.StoredProcedure;
    parameters.cmd.Parameters.AddWithValue("@CompoundID", parameters.CompoundID);
    using (var connection = new SqlConnection(parameters.connectionstring))
    using (var command = new SqlCommand(query, connection))
    {
        await connection.OpenAsync(cancellationToken);
        using (var reader = await command.ExecuteReaderAsync(cancellationToken))
        {
            if (await reader.ReadAsync(cancellationToken))
            {
                lblDeposited.Text = string.Concat("at ", reader.GetDateTime(0).ToShortDateString(), " by ",     reader.GetString(1));
            }
        }
    }
}

およびpage_load()

RegisterAsyncTask(new PageAsyncTask(GetCompoundDepositionInfoAsync));
于 2012-07-31T11:38:23.190 に答える