d2lmirrors / anolis

Anolis is the underlying project for the XPize and Vize resource switchers for Windows XP and Vista respectivly. The codebase allows for the easy swapping around of resources within Win32 executables and other files. (just adding some missing data)
GNU General Public License v2.0
1 stars 0 forks source link

Error when navigating Tree View too quickly #22

Closed Dobby233Liu closed 1 year ago

Dobby233Liu commented 1 year ago

creation date = 2009-02-28T18:24:34.03-08:00

Error in Anolis Resourcer 0.8 Beta:   Spoke to W3bbo about it; I was navigating the program's loaded DLL components too quickly in tree view. (aka: I was being too rough with the program; I need to be more gentle with it.... Patience, I guess.)   W3bbo: yeah, you were just going too fast for it W3bbo: I'll see if there's a way to queue-up the BackgroundWorker rather than interrupting it W3bbo: in future, just be more gentle with it :p   -------------------------------------Debug report below-------------------------------------

See the end of this message for details on invoking 
just-in-time (JIT) debugging instead of this dialog box.
 
************** Exception Text **************
System.InvalidOperationException: This BackgroundWorker is currently busy and cannot run multiple tasks concurrently.
   at System.ComponentModel.BackgroundWorker.RunWorkerAsync(Object argument)
   at Anolis.Resourcer.Controls.ResourceListView.ShowResourceType(ResourceType type) in C:\Documents and Settings\David\My Documents\Visual Studio Projects\Anolis\Anolis.Resourcer\Controls\ResourceListView.cs:line 112
   at Anolis.Resourcer.MainForm.ListLoad(ResourceType type) in C:\Documents and Settings\David\My Documents\Visual Studio Projects\Anolis\Anolis.Resourcer\Forms\MainForm.Partial.cs:line 361
   at Anolis.Resourcer.MainForm.__tree_AfterSelect(Object sender, TreeViewEventArgs e) in C:\Documents and Settings\David\My Documents\Visual Studio Projects\Anolis\Anolis.Resourcer\Forms\MainForm.cs:line 101
   at System.Windows.Forms.TreeView.OnAfterSelect(TreeViewEventArgs e)
   at System.Windows.Forms.TreeView.TvnSelected(NMTREEVIEW* nmtv)
   at System.Windows.Forms.TreeView.WmNotify(Message& m)
   at System.Windows.Forms.TreeView.WndProc(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
 
 
************** Loaded Assemblies **************
mscorlib
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/mscorlib.dll
----------------------------------------
Anolis.Resourcer.Merged
    Assembly Version: 0.8.3330.36117
    Win32 Version: 0.8.0.0
    CodeBase: file:///C:/Documents%20and%20Settings/Stanley/Desktop/Anolis.Resourcer.Merged.exe
----------------------------------------
System.Windows.Forms
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Windows.Forms/2.0.0.0__b77a5c561934e089/System.Windows.Forms.dll
----------------------------------------
System
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System/2.0.0.0__b77a5c561934e089/System.dll
----------------------------------------
System.Drawing
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Drawing/2.0.0.0__b03f5f7f11d50a3a/System.Drawing.dll
----------------------------------------
System.Configuration
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Configuration/2.0.0.0__b03f5f7f11d50a3a/System.Configuration.dll
----------------------------------------
System.Xml
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.42 (RTM.050727-4200)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Xml/2.0.0.0__b77a5c561934e089/System.Xml.dll
----------------------------------------
 
************** JIT Debugging **************
To enable just-in-time (JIT) debugging, the .config file for this
application or computer (machine.config) must have the
jitDebugging value set in the system.windows.forms section.
The application must also be compiled with debugging
enabled.
 
For example:
 
<configuration>
    <system.windows.forms jitDebugging="true" />
</configuration>
 
When JIT debugging is enabled, any unhandled exception
will be sent to the JIT debugger registered on the computer
rather than be handled by this dialog box.
Dobby233Liu commented 1 year ago

creation date = 2009-03-04T10:48:35.51-08:00

I've experienced these quite alot some time ago... my solution for fixing it was implementing a pool of threads. In my app there are about 7-8 concurrent threads and some of course will require access to the UI.

When working with the tree from another thread you should go for something like if (this.InvokeRequired) ... and use BeginUpdate() and EndUpdate() when using data from the tree.

This is my ThreadMgr class, feel free to adapt it to your needs.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Collections;

namespace LUR.Interop
{
    public class ThreadMgr : IDisposable, IEnumerable
    {
        private List<Thread> Pool = null;

        public ThreadMgr()
        {
            Pool = new List<Thread>();
        }

        public int Clean()
        {
            int Running = 0;
            if (Pool == null)
                return Running;

            for (int i = 0; i < Pool.Count; i++)
            {
                if (Pool[i].IsAlive)
                    Running++;
                else
                    Pool.Remove(Pool[i--]);
            }
            return Running;
        }

        public bool this[string Item, ThreadStart x]
        {
            set
            {

                Thread t = this[Item];
                if (t == null)
                {
                    try
                    {
                        if (x == null)
                            throw new System.ArgumentNullException();

                        t = this[Item] = new Thread(x);
                        t.TrySetApartmentState(ApartmentState.MTA);
                        if (value)
                            t.Start();
                    }
                    catch (System.ArgumentNullException)
                    {
                        Console.WriteLine("ThreadMgr: null or malformed parameterized thread start invoked.");
                    }
                    catch (System.Threading.ThreadStateException msg)
                    {
                        Console.WriteLine("ThreadMgr: failed " + msg.Message + " at " + msg.Source + " in " + Item + " context");
                    }
                    catch (Exception msg)
                    {
                        Console.WriteLine("ThreadMgr: unrecoverable fault caused by " + msg.Message + " in " + msg.StackTrace);
                    }
                }
                else
                {
                    // Ionutz: testeaza-ma!
                    MessageBox.Show(null, Item + " context is already locked or request is null; cannot instanciate.\n" +
                        "You may be trying to re-execute the same operation before waiting the previous attempt to complete", 
                        "Threading Manager", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
            }
        }

        public Thread this[string Item]
        {
            get
            {
                if ((Pool != null) && (Pool.Count > 0))
                {
                    foreach (Thread t in Pool)
                        if (t.Name == Item)
                            return t;
                }
                return null;
            }
            set
            {
                if (Pool == null)
                    Pool = new List<Thread>();

                try
                {
                    Pool.Add(value);
                    value.Name = Item;
                }
                catch (Exception msg)
                {
                    Console.WriteLine("ThreadMgr: " + msg.Message + "; " + value.Name + " override attempt with " + Item + " denied.");
                }
            }
        }

        public void Sync(string Item)
        {
            Thread t = this[Item];
            try
            {
                if (t.IsAlive)
                    t.Join();
            }
            catch { }
        }

        #region IDisposable Members

        public void Dispose()
        {
            if ((Pool != null) && (Pool.Count > 0))
            {
                for (int i = 0; i < Pool.Count; i++)
                {
                    if (Pool[i].IsAlive)
                        Pool[i].Abort();

                    Pool.Remove(Pool[i--]);
                }
            }
        }

        #endregion

        public void Recycle(string id)
        {
            try
            {
                foreach (Thread Pooled in Pool)
                {
                    if (Pooled.Name.Contains(id))
                    {
                        Pooled.Abort();
                        break;
                    }
                }
            }
            catch
            { }
        }

        #region IEnumerable Members

        public IEnumerator GetEnumerator()
        {
            foreach (Thread t in Pool)
            {
                yield return t;
            }
        }

        #endregion
    }
}
Dobby233Liu commented 1 year ago

closed date = 2009-04-10T14:29:58.64-07:00

I solved this by making the PopulateResourceType method check if the .CancelAsync method had been called. Additionally there are two layers of threads from ShowResourceType and PopulateResourceType.