ループ内でOutlook APIを多く呼び出すコードがあります。 OutlookはワーカースレッドからAPIへのアクセスが気に入らないので、メインスレッドを使用する必要があります。ネットワーククエリを行うコードの部分は、async/awaitで完全に正常ですので、UIはフリーズしません。しかし、コードがCPU集約的な部分(Outlook APIへの呼び出し)に達すると、UIが明らかにフリーズします。C#VSTOアドインでOutlook UIを反応させる方法UIスレッドでCPUを大量に使用する場合
各10ms経過後に実行されるawait Task.Delay(1)
が挿入されていますが、タイマーの分解能があまり正確ではないため(15ms)、コードが著しく遅くなります(UIのブロックは解除されますが)。 Task.Yield
代わりのTask.Delay(1)
を使用して
DateTime d1 = DateTime.Now;
int interval = 10;
foreach (SomeItem item in items)
{
// Intense access to Outlook API...
// ...
DateTime d2 = DateTime.Now;
if (d2.Subtract(d1).TotalMilliseconds > interval)
{
await Task.Delay(1);
d1 = d2;
}
}
は、UIを(MSDNはとにかくこのためTask.Yieldをお勧めしていません)のブロックを解除しません。
10msから大きな値(100ms)をに変更すると、パフォーマンスの低下が最小限に抑えられ、UIはやや反応しますが、滑らかになりません。
UIのスムーズさとパフォーマンスの間にトレードオフがあるとは限りません。おそらく、良い古いApplication.DoEvents
のようですが、現代的でお勧めの方法ですか?
ええ、OOMを使用しないと問題は解消されませんが、それは私の選択肢ではありません。 – Alex