菜鸟教程小白 发表于 2022-12-13 04:09:01

c# - Xamarin 表单后台任务仅在 ios 上打开应用程序时运行


                                            <p><ol>
<li>预期行为

<ul>
<li>ios

<ul>
<li>当应用最小化且每 5 秒收到通知时。</li>
</ul></li>
<li>安卓

<ul>
<li>当应用最小化且每 5 秒收到通知时。</li>
</ul></li>
</ul></li>
<li>实际行为

<ul>
<li>ios

<ul>
<li>应用最小化并且没有通知进来,打开应用会导致通知每 5 秒进来一次。</li>
</ul></li>
<li>安卓

<ul>
<li>当应用最小化并且每 5 秒收到一次通知时。

<blockquote>
<pre><code>//from app.xaml.cs
protected override void OnSleep()
    {
      void ScheduleNotification()
      {
            // Start a timer that runs after 5 seconds.
            Device.StartTimer(TimeSpan.FromSeconds(5), () =&gt;
            {
                System.Threading.Tasks.Task.Factory.StartNew( () =&gt;
                {
                  // Do the actual request and wait for it to finish.
                     PerformNotification();
                  // Switch back to the UI thread to update the UI
                  Device.BeginInvokeOnMainThread(() =&gt;
                  {
                        // Update the UI
                        // ...
                        // Now repeat by scheduling a new request
                        ScheduleNotification();
                        count++;
                  });
                }, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);

                // Don&#39;t repeat the timer (we will start a new timer when the request is finished)
                return false;
            });
      }
       void PerformNotification()
      {
            CrossLocalNotifications.Current.Show(&#34;title&#34;, &#34;body&#34;+ count.ToString());

      }
      ScheduleNotification();
    }
</code></pre>
</blockquote> </li>
</ul></li>
</ul></li>
</ol></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>在 iOS 上,不要求在后台运行的应用程序在后台运行的时间不能超过 10 秒。为了让一些代码在后台运行,您可以在 iOS 和 android 上实现 DependencyService。您可以将以下代码放入 iOS 上的该服务中:</p>

<pre><code>public async Task RunCodeInBackgroundMode(Func&lt;Task&gt; action, string name = &#34;MyBackgroundTaskName&#34;)
    {
      nint taskId = 0;
      var taskEnded = false;
      taskId = UIApplication.SharedApplication.BeginBackgroundTask(name, () =&gt;
      {
            //when time is up and task has not finished, call this method to finish the task to prevent the app from being terminated
            Console.WriteLine($&#34;Background task &#39;{name}&#39; got killed&#34;);
            taskEnded = true;
            UIApplication.SharedApplication.EndBackgroundTask(taskId);
      });
      await Task.Factory.StartNew(async () =&gt;
      {
            //here we run the actual task
            Console.WriteLine($&#34;Background task &#39;{name}&#39; started&#34;);
            await action();
            taskEnded = true;
            UIApplication.SharedApplication.EndBackgroundTask(taskId);
            Console.WriteLine($&#34;Background task &#39;{name}&#39; finished&#34;);
      });

      await Task.Factory.StartNew(async () =&gt;
      {
            //Just a method that logs how much time we have remaining. Usually a background task has around 180 seconds to complete.
            while (!taskEnded)
            {
                Console.WriteLine($&#34;Background task &#39;{name}&#39; time remaining: {UIApplication.SharedApplication.BackgroundTimeRemaining}&#34;);
                await Task.Delay(1000);
            }
      });
    }
</code></pre>

<p>在 Android 上,您可以使用以下代码:</p>

<pre><code>public async Task RunCodeInBackgroundMode(Func&lt;Task&gt; action, string name = &#34;MyBackgroundTaskName&#34;)
      {
            var powerManager = (PowerManager)Application.Context.GetSystemService(Context.PowerService);
            var wakeLock = powerManager.NewWakeLock(WakeLockFlags.Partial,
                                                    name);
            //acquire a partial wakelock. This prevents the phone from going to sleep as long as it is not released.
            wakeLock.Acquire();
            var taskEnded = false;

            await Task.Factory.StartNew(async () =&gt;
            {
                //here we run the actual code
                Console.WriteLine($&#34;Background task &#39;{name}&#39; started&#34;);
                await action();
                Console.WriteLine($&#34;Background task &#39;{name}&#39; finished&#34;);
                wakeLock.Release();
                taskEnded = true;
            });

            await Task.Factory.StartNew(async () =&gt;
            {
                //just a method to keep track of how long the task runs
                var stopwatch = new Stopwatch();
                stopwatch.Start();
                while (!taskEnded)
                {
                  Console.WriteLine($&#34;Background &#39;{name}&#39; task with wakelock still running ({stopwatch.Elapsed.TotalSeconds} seconds)&#34;);
                  await Task.Delay(1000);
                }
                stopwatch.Stop();
            });
      }
</code></pre>

<p>在共享项目中,您可以通过以下方式调用这些方法:</p>

<pre><code>var deviceInfoServic = ServiceLocator.Instance.Get&lt;YourService Interface here&gt;();
await deviceInfoServic.RunCodeInBackgroundMode(async () =&gt;
{
    //your code here
});
</code></pre></p>
                                   
                                                <p style="font-size: 20px;">关于c# - Xamarin 表单后台任务仅在 ios 上打开应用程序时运行,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/49542832/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/49542832/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: c# - Xamarin 表单后台任务仅在 ios 上打开应用程序时运行