1

http://software.tavlikos.com/2010/12/08/multitasking-in-ios-the-monotouch-way-part-i/の記事のコードサンプルを使用して、iOSアプリケーションのDidEnterBackgroundイベントでバックグラウンドタスクを実行します。

タスクは重くて長いタイミングです-1分近く。ユーザーがアプリケーションを強制的にフォアグラウンドに戻す場合は、タスクが終了するまで待つ必要があります。少し弱いです。

WillEnterForegroundイベントを使用しようとしました:

    public override void WillEnterForeground (UIApplication application)
    {
        if (taskId != 0) {
            Console.WriteLine("Finish previous task"); 
            application.EndBackgroundTask(taskId);
            taskId = 0;
        }
    }

ただし、タスクの終了に呼び出します。

ユーザーが完了する前にアプリに切り替えた場合、バックグラウンドタスクの実行を中断するにはどうすればよいですか?

DidEnterBackgroundコード:

    public override void DidEnterBackground (UIApplication application)
    {
        Console.WriteLine ("DidEnterBackground");

        if (taskId != 0) {
            Console.WriteLine("Finish previous task"); 
            application.EndBackgroundTask(taskId);
            taskId = 0;
        }

        taskId = application.BeginBackgroundTask(delegate {
            if (taskId != 0) {
                application.EndBackgroundTask(taskId);
                taskId = 0;
            }
        });

        Console.WriteLine("Begin task"); 
        application.InvokeOnMainThread(delegate() {
            for(int i = 0; i < 700; i++) {
                if ((i + 1) % 100 == 0)
                    Console.WriteLine("Time to remain: {0} seconds", application.BackgroundTimeRemaining); 
                //viewController.Touch();
            }
        });

        application.EndBackgroundTask(taskId);
        taskId = 0;
    }
4

1 に答える 1

2

主な問題はDidEnterBackground、同じスレッドでメソッドを呼び出しているため、forループが完了した後(または実装したタスク)にのみメソッドが返されることです。有無にInvokeOnMainThreadかかわらず、タスクは同じスレッドで実行されます。実際には、InvokeOnMainThreadすでにメインスレッドにいるため、呼び出す必要はありません。通常の状況では、これによりアプリがiOSによって終了します。ただし、最初にBeginBackgroundTaskを呼び出しているため、これは発生しません。

そのため、DidEnterBackgroundメソッドの戻りが遅れ、その間にアプリをフォアグラウンドに戻すため、タスクの終了後にWillEnterForegroundメソッドが実行されるのは正常です。これは、メソッドがまだ返されていないためにメソッドを実行できないため、その後キューに入れられるためです。WillEnterForegroundDidEnterBackground

あなたが言及した上記の記事の私の例では、を呼び出すことによって非同期的にタスクを呼び出していますnew System.Action(SomeDelegate(){}).BeginInvoke(null, null);。あなたはあなたが好きな解決策を使うことができます、私は今ほとんどを使っていThreadPoolます。

したがって、上記のDidEnterBackgroundメソッドを次のように変更します。

    public override void DidEnterBackground (UIApplication application)
    {
        Console.WriteLine ("DidEnterBackground");

        if (taskId != 0) {
            Console.WriteLine("Finish previous task"); 
            application.EndBackgroundTask(taskId);
            taskId = 0;
        }

        taskId = application.BeginBackgroundTask(delegate {
            if (taskId != 0) {
                application.EndBackgroundTask(taskId);
                taskId = 0;
            }
        });

        Console.WriteLine("Begin task");
        ThreadPool.QueueUserWorkItem(delegate {

            application.InvokeOnMainThread(delegate() {
                for(int i = 0; i < 700; i++) {
                    if ((i + 1) % 100 == 0)
                        Console.WriteLine("Time to remain: {0} seconds", application.BackgroundTimeRemaining); 
                    //viewController.Touch();
                }

                // EndBackgroundTask must also be executed on the main thread.
                application.EndBackgroundTask(taskId);
                taskId = 0;
            });

        });
    }
于 2012-07-16T12:45:12.220 に答える