1

別のサードパーティ サービスを呼び出すためにマルチ スレッドを実装する必要がある WCF サービスを作成しています。

LINQ を使用して「リスト」を作成し、オブジェクトのリストをクライアントに送信しています。

「MyObject」には 5 つのプロパティがあります。

  • 3 テーブルに静的に格納
  • 2 サードパーティ サービスによって動的に計算されます。

30 秒のタイムアウトで、2 つの動的プロパティを読み取るためにスレッドを生成する必要があります。例:

リストに 6 つのオブジェクトがある場合、

  • 2 つのプロパティのそれぞれに対してサード パーティ サービスを呼び出す、非同期で並列に実行される 6 つのスレッドを生成する必要があります。
  • 30 秒以内にすべての結果が得られたら、6 つのオブジェクトとすべてのプロパティをクライアントに送信します。
  • 30 秒以内にどのオブジェクトのプロパティも受信しない場合は、そのオブジェクトのプロパティを NULL に設定し、オブジェクトのリストをクライアントに返す必要があります。

私のコードは次のようになります。

List<Dials> lstDial = new List<Dials>();
foreach(var c in dialsToShow)
{
    int threadId;
    AsyncMethodCaller caller =
        new AsyncMethodCaller(MyMethodThatCalls3rdPartyService);

    IAsyncResult result = caller.BeginInvoke(userName, out threadId, null, null);

    while (!result.AsyncWaitHandle.WaitOne(30000, false))
         avgBI = caller.EndInvoke(out threadId, result);

    property4 = avgBI[0];
    property5= avgBI[1]; 

    var dashboardObj = _repository.FindQueryable<DashboardDial_Tbl>()
                   .Select(p => new DialDetails()
                   {
                       Id = p.DialId,
                       Name= p.DialName,
                       Type = p.DialType,
                       IndividualStat = property4,
                       GroupStat = proprty5         
                    }).SingleOrDefault();
      dials.Add(dashboardObj); 
}
reponse.dialsList = dials;

サードパーティ サービスを呼び出すメソッドにはデリゲートがあります。次のようになります。

public delegate List<string> AsyncMethodCaller(
    string methodName, out int threadId);

private List<string> MyMethodThatCalls3rdPartyService(
    string userName, out int threadId)
{
    //Call the service
}

別の方法でマルチスレッドを使用してこれを達成するのを手伝ってもらえますか? .Net 4.0 と VS2012 を使用しています。

4

1 に答える 1

1

Parallel並行タスクを並行して実行するために使用できます。

public void DoStuff()
{
    var input = new[] {2, 3, 4};

    var results = new ConcurrentBag<string>();

    Parallel.ForEach(input, value =>
        {
            value += 10;
            results.Add(value.ToString());
        });

    foreach (var result in results)
    {
        Console.WriteLine(result);
    }
}

タイムアウトを行うには、匿名メソッド内で何かを行うか、CancellationToken.

Taskまたは、オブジェクト自体を使用できます。

public void DoStuff()
{
    int input = 2;

    Task<string> task = Task<string>.Factory.StartNew(() =>
        {
            var output = (input + 10).ToString();
            return output;
        });

    //use this if you want to wait for all your tasks to complete
    Task.WaitAll(task);

    //Calling result will implicitly cause a wait if the task is not complete
    Console.WriteLine(task.Result);
}

タスクをタイムアウトするには、すべてのタスクで個別にタイムアウトを呼び出すWaitか、でタイムアウトを指定するWaitAllか、CancellationToken を再度使用できます。

Task.WaitAll(new[] {task}, TimeSpan.FromSeconds(10));

編集

私はあなたの例の実装を提供しようとしましたが、いくつかの明確化が必要なビットがあり、例の一部が結びついていないため、いくつかの仮定を立てる必要がありました:

  1. ダイヤル = DialDetails
  2. lstDial = ダイヤル
  3. 「30 秒以内にどのオブジェクトのプロパティも取得できない場合、そのオブジェクトのプロパティを NULL に設定する必要があります」とは、そのオブジェクトではなく、残りのアイテムが必要であることを意味します。

並列 foreach とタスクを組み合わせて使用​​しました。

var dials = new List<DialDetails>();
Parallel.ForEach(dialsToShow, c =>
    {
        var task = Task<IList<string>>.Factory.StartNew(
            () => MyMethodThatCalls3rdPartyService(userName));
        // Get the item from the database while calling the service
        // However there appears to be no search going on here
        // the same type will always come back right?
        var dashboardObj = _repository.FindQueryable<DashboardDial_Tbl>()
                    .Select(p => new DialDetails()
                    {
                        Id = p.DialId,
                        Name= p.DialName,
                        Type = p.DialType      
                    }).SingleOrDefault();

        //Wait until the timeout
        task.Wait(TimeSpan.FromSeconds(30));

        //If it did not timeout or no other error occurred us the results
        if (dashboardObj != null && task.Status == TaskStatus.RanToCompletion)
        {
            //Need to do some checking here for indexes
            dashboardObj.IndividualStat = task.Result[0];
            dashboardObj.GroupStat = task.Result[1];
            dials.Add(dashboardObj);
        }
    });
reponse.dialsList = dials;

private IList<string> MyMethodThatCalls3rdPartyService(string userName)
{
    //Call the service
}
于 2013-09-19T15:21:32.487 に答える