0

我要求这样做是为了更深入地了解 Mono for Android,并在支持我的移动应用程序时做好更好的准备......

我注意到,当从“主启动器”活动中启动的工作线程调用 StartService 时,服务的 OnStartCommand 中的线程 ID 与活动线程 ID(1)相同,而不是启动它的工作线程 ID( 3)。

这是一个更抽象的表示:

myActivity : Activity
{
  OnCreate
  {
    print_thread_id()  // 1

    start(thread_func) 
  }

  thread_func() 
  {
    print_thread_id()  // 3 (not 2!, but anyway ...)

    StartService(myService)
  }
}

myService : Service
{
  OnStartCommand
  {
    print_thread_id()   // 1 also!!!
  }
}

我还注意到在我的工作线程 thread_func 中,即使服务继续运行,StartService 也会返回。我认为对 StartService 的调用会阻塞,直到 myService 退出。

为什么 myService.OnStartCommand 中的线程 ID 与 thread_func 的不同,thread_func 的父级不是调用 StartService 的地方吗?

谢谢。

4

2 回答 2

1

我没有看到你描述的行为。新线程中的方法准确地报告了自己的 id。这是一个非常简单的类,可以帮助您解决环境中的差异:

namespace ThreadTest
{
    [Activity (Label = "ThreadTest", MainLauncher = true)]
    public class Activity1 : Activity
    {
        int count = 1;

        protected override void OnCreate (Bundle bundle)
        {
            base.OnCreate (bundle);

            SetContentView (Resource.Layout.Main);

            MyService service = new MyService();
            Console.WriteLine("First Thread id: " + Thread.CurrentThread.ManagedThreadId);
            Thread oThread = new Thread(new ThreadStart(service.StartCommand));
            oThread.Start();
        }
    }

    public class MyService : Android.App.Service
    {
        public override IBinder OnBind(Intent intent)
        {
            return null;
        }
        public void StartCommand()
        {
            Console.WriteLine("New Thread id: " + Thread.CurrentThread.ManagedThreadId);
        }
    }
}

输出是:

第一个线程 ID:1

新线程 ID:4

于 2012-07-12T20:34:23.673 回答
0

谢谢joates...我可能对正确使用服务有误解。这是我正在做的事情:

namespace ThreadTest  
{  
  [Activity (Label = "ThreadTest", MainLauncher = true)]  
  public class myActivity : Activity  
  {
    protected override void OnCreate(Bundle savedInstanceState)
    {
      base.OnCreate(savedInstanceState);
      SetContentView(Resource.Layout.Main);

      Console.WriteLine("Main Thread id: " + Thread.CurrentThread.ManagedThreadId); 

      Thread serviceWorker = new Thread(new ThreadStart(serviceThread));
      serviceWorker.Start();
    }

    private void serviceThread()
    {
      Console.WriteLine("Child Thread id: " + Thread.CurrentThread.ManagedThreadId); 

      StartService(new Intent(this, typeof(myService)));
    }
  }

  public class myService : Service
  {
    public override IBinder OnBind(Intent intent)
    {
      throw new NotImplementedException();
    }

    public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
    {
      Console.WriteLine("Service Thread id: " + Thread.CurrentThread.ManagedThreadId); 
    }
  }
}

这是错误的,还是只是一种不同的方法?如果要使用 StartService 方法来启动服务,而不是在上面如何启动它,这会是正确的方法吗?

按照您建议的方式,您将服务对象的方法分配给主活动中的工作线程,然后通过 ThreadStart() 启动它。我的方法实际上是通过 StartService 启动服务本身(我从子线程中调用的唯一原因是 UI 不会被阻塞,而不是 b/c 是必需的)。

我提出的方式似乎是正确的,因为我让 adroid/mono 管理服务的加载和调用(StartService 最终将导致覆盖 OnStartCommand 被调用)。我不确定您的方式是否真的会导致显式创建服务(尽管我将对此进行测试),我知道用我的方法是有的。

您认为哪种方式更“正确”?

于 2012-07-12T21:34:02.480 回答