RunUO Community

This is a sample guest message. Register a free account today to become a member! Once signed in, you'll be able to participate on this site by adding your own topics and posts, as well as connect with other members through your own private inbox!

Cross-thread MessageBox.Show() ?

Cheetah2003

Wanderer
Cross-thread MessageBox.Show() ?

I've been working on a GUI for RunUO for a couple months now.

I discovered MessageBox.Show() and need to call this method from a few places in World.cs, but I get that irritating '{"Cross-thread operation not valid: Control 'RunUO_UI' accessed from a thread other than the thread it was created on."}'

So I had to disable the checking for this, currently. But I was wondering if anyone knew the proper way to cross-thread MessageBox.Show?

I know how to use delegates to do things like modify the text of a control and so forth, but creating a new control as a child of the form on another thread... I can't seem to locate any documentation on how to do that in MSDN.
 

noobie

Wanderer
there is a class called backgroundworker. there is lots of examples..

google:Cross-thread operation not valid
 
You still looking for a way to avoid the "Cross-Thread Operation Not Valid" exception?

I happen to be looking for something to help me out of this paticular issue ... without screwing with some of the other stuff again.

SafeInvokeHelper.cs
Code:
using System;
using System.Collections;
using System.Reflection;
using System.Reflection.Emit;

public class SafeInvokeHelper
{
    static readonly ModuleBuilder builder;
    static readonly AssemblyBuilder myAsmBuilder;
    static readonly Hashtable methodLookup;

    static SafeInvokeHelper()
    {
        AssemblyName name = new AssemblyName();
        name.Name = "temp";
        myAsmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run);
        builder = myAsmBuilder.DefineDynamicModule("TempModule");
        methodLookup = new Hashtable();
    }

    public static object Invoke(System.Windows.Forms.Control obj, string methodName, params object[] paramValues)
    {
        Delegate del = null;
        string key = obj.GetType().Name + "." + methodName;
        Type tp;

        lock (methodLookup) 
        {
            if (methodLookup.Contains(key)) 
                tp = (Type)methodLookup[key];
            else
            {
                Type[] paramList = new Type[obj.GetType().GetMethod(methodName).GetParameters().Length];
                int n = 0;
                foreach (ParameterInfo pi in obj.GetType().GetMethod(methodName).GetParameters()) paramList[n++] = pi.ParameterType;
                TypeBuilder typeB = builder.DefineType("Del_" +  obj.GetType().Name + "_" + methodName, TypeAttributes.Class | TypeAttributes.AutoLayout | TypeAttributes.Public |  TypeAttributes.Sealed, typeof(MulticastDelegate), PackingSize.Unspecified);
                ConstructorBuilder conB = typeB.DefineConstructor(MethodAttributes.HideBySig | MethodAttributes.SpecialName |            MethodAttributes.RTSpecialName, CallingConventions.Standard, new Type[] { typeof(object), typeof(IntPtr) });
                conB.SetImplementationFlags(MethodImplAttributes.Runtime);
                MethodBuilder mb = typeB.DefineMethod( "Invoke", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, obj.GetType().GetMethod(methodName).ReturnType, paramList );
                mb.SetImplementationFlags( MethodImplAttributes.Runtime ); 
                tp = typeB.CreateType();
                methodLookup.Add(key, tp);
            }
        }

        del = MulticastDelegate.CreateDelegate(tp, obj, methodName);
        return obj.Invoke(del, paramValues);
    }
}

Usage:
Code:
SafeInvokeHelper.Invoke( Control, "the_method", parms )

Would look like this.
Code:
SafeInvokeHelper.Invoke( m_PatchSwapper, "Update_ProgressBar", percent <= 100 ? percent : 100, true );
SafeInvokeHelper.Invoke( m_PatchSwapper, "Update_Label", m_PatchSwapper._PercentLabel, String.Format( "{0}%", percent <= 100 ? percent : 100 ) );

Havnt tested it with a MessageBox before, not sure if it will even work with one. Its worth a shot though eh?


SafeInvokeHelper - Author/Original Article
 

Jeff

Lord
You should look into anonymous methods :)

for instance, lets say you want to invoke progress bar update from another thread.

Code:
int progress = 50;
progressBar.Invoke((MethodInvoker)delegate
{
   progressBar.Value = 50;
   progressBar.Invalidate();
});

its that simple.

I personally seen your code as more bloat but to each his own. Looks good tho.

@topic MessageBox.Show()

should simply do something like

Code:
myForm.Invoke( (MethodInvoker)delegate
{
  MessageBox.Show( "message", "caption" );
});
 

Jeff

Lord
o0_Sithid_0o said:
I didnt write the SafeInvokeHelper class, I just happen to stumble onto it and decided to give it a try. Its been working fine for me.

SafeInvokeHelper
I dont doubt it works, but it is 1.0 code :( tbh 1.0 .net can lick my sack, ArrayList....:shutters: :)
 

noobie

Wanderer
why do you think it is 1.0 code?

@sithid:btw, there is a better solution on the same link if you havent noticed..
 

Jeff

Lord
noobie said:
why do you think it is 1.0 code?
ArrayList and Hashtable is why, tbh if u had 2.0 why in gods name would you use those. They do nothing but make room for error and slow your application.
 
Top