Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. need to make an asynchronous call to a method that accepts arguments and then modifies form

need to make an asynchronous call to a method that accepts arguments and then modifies form

Scheduled Pinned Locked Moved C#
lounge
6 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • X Offline
    X Offline
    x0lubi
    wrote on last edited by
    #1

    hi all. i need to make a call to a method asynchronously. this method accepts arguments. the method also returns a value that is then used to modify a form obviously created by the main thread. to keep things simple, i created a prototype of what i'm trying to do. here's the code:

    public partial class Form1 : Form
    {
    public delegate int SomeMethod();

        public Form1()
        {
            InitializeComponent();
        }
    
        private void button1\_Click(object sender, EventArgs e)
        {
            //AddToList(IntFetcher.SlowFetch());
            SomeMethod method = IntFetcher.SlowFetch;
            method.BeginInvoke(EndFetchInt, method);
        }
    
        public void EndFetchInt(IAsyncResult result)
        {
            SomeMethod method = result.AsyncState as SomeMethod;
            int i = method.EndInvoke(result);
            MethodInvoker mi = new MethodInvoker(this.AddToList);
            this.BeginInvoke(mi, i);
        }
        
        public void AddToList()
        {
            int i = 0;
            ListViewItem lvi = new ListViewItem();
            lvi.Text = i.ToString();
            lvi.SubItems.Add(DateTime.Now.ToString());
            listView1.Items.Add(lvi);
        }
    
        public void AddToList(int data)
        {
            ListViewItem lvi = new ListViewItem();
            lvi.Text = data.ToString();
            lvi.SubItems.Add(DateTime.Now.ToString());
            listView1.Items.Add(lvi);
        }
    
    }
    
    public static class IntFetcher
    {
        public static int SlowFetch()
        {
            // Simulate a slow i/o process
            Thread.Sleep(3150); 
            Random random = new Random(DateTime.Now.Millisecond);
            return random.Next(100, 500);
        }
    }
    

    I had to create the AddToList() method to be confirm if the code was being called at all and to determine if it could modify the listview control. It did. But i still couldnt figure out a way to pass the value returned from the function to it. I used MethodInvoker cos without it, I got an exception telling me that the running thread could not modify the control as it was created by the main thread. Any contributions will be appreciated. Thanks.

    J W 2 Replies Last reply
    0
    • X x0lubi

      hi all. i need to make a call to a method asynchronously. this method accepts arguments. the method also returns a value that is then used to modify a form obviously created by the main thread. to keep things simple, i created a prototype of what i'm trying to do. here's the code:

      public partial class Form1 : Form
      {
      public delegate int SomeMethod();

          public Form1()
          {
              InitializeComponent();
          }
      
          private void button1\_Click(object sender, EventArgs e)
          {
              //AddToList(IntFetcher.SlowFetch());
              SomeMethod method = IntFetcher.SlowFetch;
              method.BeginInvoke(EndFetchInt, method);
          }
      
          public void EndFetchInt(IAsyncResult result)
          {
              SomeMethod method = result.AsyncState as SomeMethod;
              int i = method.EndInvoke(result);
              MethodInvoker mi = new MethodInvoker(this.AddToList);
              this.BeginInvoke(mi, i);
          }
          
          public void AddToList()
          {
              int i = 0;
              ListViewItem lvi = new ListViewItem();
              lvi.Text = i.ToString();
              lvi.SubItems.Add(DateTime.Now.ToString());
              listView1.Items.Add(lvi);
          }
      
          public void AddToList(int data)
          {
              ListViewItem lvi = new ListViewItem();
              lvi.Text = data.ToString();
              lvi.SubItems.Add(DateTime.Now.ToString());
              listView1.Items.Add(lvi);
          }
      
      }
      
      public static class IntFetcher
      {
          public static int SlowFetch()
          {
              // Simulate a slow i/o process
              Thread.Sleep(3150); 
              Random random = new Random(DateTime.Now.Millisecond);
              return random.Next(100, 500);
          }
      }
      

      I had to create the AddToList() method to be confirm if the code was being called at all and to determine if it could modify the listview control. It did. But i still couldnt figure out a way to pass the value returned from the function to it. I used MethodInvoker cos without it, I got an exception telling me that the running thread could not modify the control as it was created by the main thread. Any contributions will be appreciated. Thanks.

      J Offline
      J Offline
      Jaffer Mumtaz
      wrote on last edited by
      #2

      Hi, Have a look at the link. Hope this helps. http://en.csharp-online.net/CSharp_Delegates_and_Events%E2%80%94Asynchronous_method_calls[^]

      X 1 Reply Last reply
      0
      • J Jaffer Mumtaz

        Hi, Have a look at the link. Hope this helps. http://en.csharp-online.net/CSharp_Delegates_and_Events%E2%80%94Asynchronous_method_calls[^]

        X Offline
        X Offline
        x0lubi
        wrote on last edited by
        #3

        i still got this exception Cross-thread operation not valid: Control 'listView1' accessed from a thread other than the thread it was created on. while calling the AddToList() method directly from the callback method using the procedure outlined on that url. combed thru msdn and got this url http://msdn.microsoft.com/en-us/library/ms171728.aspx which is supposed to help make thread-safe calls to windows form controls. trying to understand the methods outlined there.

        1 Reply Last reply
        0
        • X x0lubi

          hi all. i need to make a call to a method asynchronously. this method accepts arguments. the method also returns a value that is then used to modify a form obviously created by the main thread. to keep things simple, i created a prototype of what i'm trying to do. here's the code:

          public partial class Form1 : Form
          {
          public delegate int SomeMethod();

              public Form1()
              {
                  InitializeComponent();
              }
          
              private void button1\_Click(object sender, EventArgs e)
              {
                  //AddToList(IntFetcher.SlowFetch());
                  SomeMethod method = IntFetcher.SlowFetch;
                  method.BeginInvoke(EndFetchInt, method);
              }
          
              public void EndFetchInt(IAsyncResult result)
              {
                  SomeMethod method = result.AsyncState as SomeMethod;
                  int i = method.EndInvoke(result);
                  MethodInvoker mi = new MethodInvoker(this.AddToList);
                  this.BeginInvoke(mi, i);
              }
              
              public void AddToList()
              {
                  int i = 0;
                  ListViewItem lvi = new ListViewItem();
                  lvi.Text = i.ToString();
                  lvi.SubItems.Add(DateTime.Now.ToString());
                  listView1.Items.Add(lvi);
              }
          
              public void AddToList(int data)
              {
                  ListViewItem lvi = new ListViewItem();
                  lvi.Text = data.ToString();
                  lvi.SubItems.Add(DateTime.Now.ToString());
                  listView1.Items.Add(lvi);
              }
          
          }
          
          public static class IntFetcher
          {
              public static int SlowFetch()
              {
                  // Simulate a slow i/o process
                  Thread.Sleep(3150); 
                  Random random = new Random(DateTime.Now.Millisecond);
                  return random.Next(100, 500);
              }
          }
          

          I had to create the AddToList() method to be confirm if the code was being called at all and to determine if it could modify the listview control. It did. But i still couldnt figure out a way to pass the value returned from the function to it. I used MethodInvoker cos without it, I got an exception telling me that the running thread could not modify the control as it was created by the main thread. Any contributions will be appreciated. Thanks.

          W Offline
          W Offline
          Wendelius
          wrote on last edited by
          #4

          First, based on documentation for MethodInvoker: This API supports the .NET Framework infrastructure and is not intended to be used directly from your code Second, presumably the MethodInvoker executes the method passed in another thread so it basically the problem is exactly what the error says. Take a look at BackgroundWorker Class[^]. I believe it would be helpful in your case.

          The need to optimize rises from a bad design

          X 1 Reply Last reply
          0
          • W Wendelius

            First, based on documentation for MethodInvoker: This API supports the .NET Framework infrastructure and is not intended to be used directly from your code Second, presumably the MethodInvoker executes the method passed in another thread so it basically the problem is exactly what the error says. Take a look at BackgroundWorker Class[^]. I believe it would be helpful in your case.

            The need to optimize rises from a bad design

            X Offline
            X Offline
            x0lubi
            wrote on last edited by
            #5

            Thanks Mika, but i got it working already. the problem i had was marshalling the background thread to the main one. this was the modification i made to get it to work.

                public void EndFetchInt(IAsyncResult result)
                {
                    SomeMethod method = (SomeMethod)result.AsyncState;
                    int i = method.EndInvoke(result);
            
                    //MethodInvoker mi = new MethodInvoker(this.AddToList);
                    //this.BeginInvoke(mi, i);
                    
                    AddToList(i);
                }
            
                delegate void \_addToList(int data);
            
                public void AddToList(int data)
                {
                    if (this.listView1.InvokeRequired)
                    {
                        this.Invoke(new \_addToList(AddToList), data);
                    }
                    else
                    {
                        ListViewItem lvi = new ListViewItem();
                        lvi.Text = data.ToString();
                        lvi.SubItems.Add(DateTime.Now.ToString());
                        listView1.Items.Add(lvi);
                    }
                }
            

            i would have had to do the same if even if i had used the BackgroundWorker class.

            W 1 Reply Last reply
            0
            • X x0lubi

              Thanks Mika, but i got it working already. the problem i had was marshalling the background thread to the main one. this was the modification i made to get it to work.

                  public void EndFetchInt(IAsyncResult result)
                  {
                      SomeMethod method = (SomeMethod)result.AsyncState;
                      int i = method.EndInvoke(result);
              
                      //MethodInvoker mi = new MethodInvoker(this.AddToList);
                      //this.BeginInvoke(mi, i);
                      
                      AddToList(i);
                  }
              
                  delegate void \_addToList(int data);
              
                  public void AddToList(int data)
                  {
                      if (this.listView1.InvokeRequired)
                      {
                          this.Invoke(new \_addToList(AddToList), data);
                      }
                      else
                      {
                          ListViewItem lvi = new ListViewItem();
                          lvi.Text = data.ToString();
                          lvi.SubItems.Add(DateTime.Now.ToString());
                          listView1.Items.Add(lvi);
                      }
                  }
              

              i would have had to do the same if even if i had used the BackgroundWorker class.

              W Offline
              W Offline
              Wendelius
              wrote on last edited by
              #6

              Glad you got it solved! Yeah, you have had to do the same in every implementation, but there was these two reasons why I suggested BackgroundWorker: - if I understood correctly, MethodInvoker shouldn't be used. If it's internal, it's not well documented and there are no quarantees for backward compatibility in future versions - with BW the model is easier to implement and therefore also more understandable But then again, are those valid reasons at all fully depend on your needs. Happy coding :)

              The need to optimize rises from a bad design

              1 Reply Last reply
              0
              Reply
              • Reply as topic
              Log in to reply
              • Oldest to Newest
              • Newest to Oldest
              • Most Votes


              • Login

              • Don't have an account? Register

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • World
              • Users
              • Groups