2

データの読み込みとフィルタリングをスレッドセーフにするのに少し問題があります。

BackgroundWorker を介してすべてのデータ生成を処理する、コントロールの基本クラスの次のコード。これにより、"this.DataWorker.RunWorkerAsync()" でエラーが発生し、BackgroundWorker がビジー状態であることがわかります。

/// <summary>
/// Handles the population of the form data.
/// </summary>
/// <param name="reload">Whether to pull data back from the WebService.</param>
public void Populate(bool reload)
{
    if (!this.DataWorker.IsBusy)
    {

        // Disable the filter options
        IvdSession.Instance.FilterManager.SetEnabledState(this.GetType(), false);

        // Perform the population
        this.DataWorker.RunWorkerAsync(reload);

    }
    else if (!reload)
    {
        // If the data worker is busy and this is a not reload, then something bad has happened (i.e. the filter has run during a reload.)
        throw new InvalidOperationException("The DataWorker was busy whilst asked to reload.");
    }
}

コードは2 つの可能な場所で呼び出されます。まず、コントロールがオンになっているフォームのタイマーによって:

private void tmrAutoRefresh_Tick(object sender, EventArgs e)
{
    if (!(this.CurrentBody == null))
    {
        this.CurrentBody.Populate(true);
    }
}

次に、ユーザーが多数のドロップダウン リストからフィルター オプションを選択すると、次のようになります。

public void Filter()
{
    if (!m_BlockFilter)
    {
        IvdInstance.Main.CurrentBody.FirstRun = true;
        IvdInstance.Main.CurrentBody.Populate(false);
    }
}

メイン フォームの Timer は 60 秒ごとに実行され、Populate メソッドに true を渡します。reload を true として渡すと、WebService から新しいデータ セットを取得する必要があることが BackgroundWorker に通知されます。

void dataWorker_DoWork(object sender, DoWorkEventArgs e)
{

    try
    {

        if (base.FirstRun)
        {
            base.CleanListView();
        }

        if ((bool)e.Argument)
        {
            byte[] serialized = IvdSession.DataAccess.GetServiceCalls(IvdSession.Instance.Company.Description, IvdSession.Instance.Company.Password, null);
            m_DataCollection = new DalCollection<ServiceCallEntity>(serialized);
        }

        List<ServiceCallEntity> collection = this.ApplyFilter();
        base.HandlePopulation<ServiceCallEntity>(collection, e);

    }
    catch (WebException ex)
    {
        // Ignore - Thrown when user clicks cancel
    }
    catch (System.Web.Services.Protocols.SoapException ex)
    {
        // Log error on server and stay transparent to user
        base.LogError(ex);
    }
    catch (System.Data.SqlClient.SqlException ex)
    {
        // Inform user that the database is unavailable
        base.HandleSystemUnavailable(ex);
    }

}

私の知る限り、タイマーが人口イベントを発生させるのとまったく同時にフィルターオプションをクリックすると、エラーが発生します。Populate メソッド、つまりロックに欠けているものがあると思いますが、このインスタンスで正しく使用する方法がわかりません。

コードはユーザー入力に優先されます。ユーザーがフィルター オプションを選択すると、自動更新がブロックされます。自動更新が起動すると、フィルター オプションは一時的に無効になります。それらが同時に発生した場合、ユーザー入力が優先されます (可能な場合)。

誰かが助けてくれることを願っています!

4

2 に答える 2