static readonly System.Threading.Tasks.Schedulers.StaTaskScheduler _staTaskScheduler = new System.Threading.Tasks.Schedulers.StaTaskScheduler(4); //tested: without StaTaskScheduler would be 4 threads. With 3 the UI thread is slightly faster. #else async void _GetIconAsync(AsyncResult state) { var task = Task.Run(() => { if (_canceled) { return; } //Thread.Sleep(500); var k = state; k.hIcon = GetFileIconHandle(k.file, _iconSize, _iconFlags); }); await task; //async continuation if (_canceled) { Api.DestroyIcon(state.hIcon); } else { _callback(state, _objCommon); //even if hi == default, it can be useful if (--_counter == 0) { if (_onFinished != null) { _onFinished(_objCommon); } _host._works.Remove(this); _host = null; } } }
void _GetIconAsync(Result state) { Util.ThreadPoolSTA_.SubmitCallback(state, d => { //this code runs in a thread pool thread if (_canceled) { d.completionCallback = null; return; } //Thread.Sleep(10); var k = d.state as Result; k.hIcon = AIcon.GetFileIconHandle(k.file, _iconSize, _iconFlags); //var hi = GetFileIconHandle(k.file, _iconSize, _iconFlags); //if(0!=(_iconFlags&IconGetFlags.NeedImage) && _nPending>20) { /*AOutput.Write(_nPending);*/ k.image = HandleToImage(hi); } else k.hIcon = hi; //AOutput.Write("1"); //Prevent overflowing the message queue and the number of icon handles. //Because bad things start when eg toolbar icon count is more than 3000 and they are extracted faster than consumed. //But don't make the threshold too low, because then may need to wait unnecessarily, and it makes slower. if (Interlocked.Increment(ref _nPending) >= 900) { //AOutput.Write(_nPending); //var perf = APerf.Create(); Thread.Sleep(10); //while(_nPending >= 900) Thread.Sleep(10); //perf.NW(); } }, o => { //this code runs in the caller's thread Interlocked.Decrement(ref _nPending); //AOutput.Write("2"); var k = o as Result; if (_canceled) { Api.DestroyIcon(k.hIcon); } else { _callback(k, _objCommon, --_counter); //even if hIcon == default, it can be useful if (_counter == 0) { _host._works.Remove(this); _host = null; Debug.Assert(_nPending == 0); } } }); }
internal void GetAllAsync(IconsAsync_ host, Callback callback, int iconSize, IconGetFlags flags, object objCommon) { Debug.Assert(_callback == null); //must be called once _host = host; _callback = callback; _iconSize = iconSize; _iconFlags = flags; _objCommon = objCommon; _counter = _host._files.Count; using (new Util.EnsureWindowsFormsSynchronizationContext_()) { foreach (var v in _host._files) { if (!v.file.NE()) { _GetIconAsync(new Result(v.file, v.obj)); } } } }