c#uwp:在每个可用的逻辑cpu上发送webview导航和捕获

时间:2017-10-17 22:03:14

标签: c# multithreading webview uwp

我正在学习代码并做一个捕获谷歌街景截屏的应用程序。很多截图。我想找到一种并行查询的方法。

这里是单个查询的代码:

// prepare the html code  string in a dictionary (I use street view in a iframe)   
Dictionary<int, string> htmlCode= SetUpURLListHD();

// prepare the webview and display it on a grid
WebView saveWebView = new WebView();
saveWebView.Width = Width;
saveWebView.Height = Height;
TopGrid.Children.Add(saveWebView);

// navigate to string, wait a moment until street view completely loaded, do a capture, save it to file m.jpg with custom function
 for (var m = 0; m < htmlCode.Count; m++)
            {
                saveWebView.NavigateToString(htmlCode[m]);
                await Task.Delay(2000);
                await saveWebView.CapturePreviewToStreamAsync(stream);
                await SaveSSAsync(stream, m);
             }

我有16个逻辑cpu,64个ram和一个光纤连接。所以,我想要做到16次查询。

为此,我想我需要编写16个函数来创建16个webview:

async Task ProcessURLHD1Async(string url, int i, int width, int height, ulong firstFrameSize)
        {
            try
            {
                WebView saveWebView1 = new WebView();
                saveWebView1.Width = width;
                saveWebView1.Height = height;
                TopGrid.Children.Add(saveWebView1);
                ...

第二功能:

async Task ProcessURLHD2Async(string url, int i, int width, int height, ulong firstFrameSize)
        {
            try
            {
                WebView saveWebView2 = new WebView();
                saveWebView2.Width = width;
                saveWebView2.Height = height;
                TopGrid.Children.Add(saveWebView2);

等等...

我不知道这是否是正确的方法。 我现在正在尝试同时执行16个函数,当一个函数结束时,再次使用下一个html代码(在字典中编码的下一个街景图像)。 现在,没有结果。 欢迎任何帮助。

谢谢!

ps:这是我编写数周后的第一条消息,感谢所有在本网站提供帮助的人,对我非常有用!

编辑:好的!我发现 !这很难看,但速度很快! :

// below namespace :

    public static class DispatcherTaskExtensions
    {
        public static async Task<T> RunTaskAsync<T>(this CoreDispatcher dispatcher,
            Func<Task<T>> func, CoreDispatcherPriority priority = CoreDispatcherPriority.Normal)
        {
            var taskCompletionSource = new TaskCompletionSource<T>();
            await dispatcher.RunAsync(priority, async () =>
            {
                try
                {
                    taskCompletionSource.SetResult(await func());
                }
                catch (Exception ex)
                {
                    taskCompletionSource.SetException(ex);
                }
            });
            return await taskCompletionSource.Task;
        }

        // There is no TaskCompletionSource<void> so we use a bool that we throw away.
        public static async Task RunTaskAsync(this CoreDispatcher dispatcher,
            Func<Task> func, CoreDispatcherPriority priority = CoreDispatcherPriority.Normal) =>
            await RunTaskAsync(dispatcher, async () => { await func(); return false; }, priority);
    }

//Call function on click
private async void GetHDMT_Click(object sender, RoutedEventArgs e)
        {
            if (outputFolder == null)
            {
                var folderPicker = new Windows.Storage.Pickers.FolderPicker();
                folderPicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.Desktop;
                folderPicker.FileTypeFilter.Add("*");

                outputFolder = await folderPicker.PickSingleFolderAsync();
                if (outputFolder != null)
                {
                    // Application now has read/write access to all contents in the picked folder
                    // (including other sub-folder contents)
                    Windows.Storage.AccessCache.StorageApplicationPermissions.
                    FutureAccessList.AddOrReplace("PickedFolderToken", outputFolder);
                }
                else
                {
                }
            }
            if (mylat.Count > 0)
            {

                await GetImagesAsyncHD();
            }
        }


 private async Task GetImagesAsyncHD()
        {
// Make a list of html code with street view iframe.
            var Width = 4000;
            var Height = 2000;
            var urls = SetUpURLListHD(Width, Height);


            WebView saveWebView0 = new WebView
            {
                Width = Width,
                Height = Height
            };
            TopGrid.Children.Add(saveWebView0);
            WebView saveWebView1 = new WebView
            {
                Width = Width,
                Height = Height
            };
            TopGrid.Children.Add(saveWebView1);
            WebView saveWebView2 = new WebView
            {
                Width = Width,
                Height = Height
            };
            TopGrid.Children.Add(saveWebView2);
            WebView saveWebView3 = new WebView
            {
                Width = Width,
                Height = Height
            };
            TopGrid.Children.Add(saveWebView3); WebView 
                saveWebView4 = new WebView
            {
                Width = Width,
                Height = Height
            };
            TopGrid.Children.Add(saveWebView4);
            WebView saveWebView5 = new WebView
            {
                Width = Width,
                Height = Height
            };
            TopGrid.Children.Add(saveWebView5);
            WebView saveWebView6 = new WebView
            {
                Width = Width,
                Height = Height
            };
            TopGrid.Children.Add(saveWebView6);
            WebView saveWebView7 = new WebView
            {
                Width = Width,
                Height = Height
            };
            TopGrid.Children.Add(saveWebView7); WebView
                saveWebView8 = new WebView
            {
                Width = Width,
                Height = Height
            };
            TopGrid.Children.Add(saveWebView8);
            WebView saveWebView9 = new WebView
            {
                Width = Width,
                Height = Height
            };
            TopGrid.Children.Add(saveWebView9);
            WebView saveWebView10 = new WebView
            {
                Width = Width,
                Height = Height
            };
            TopGrid.Children.Add(saveWebView10);
            WebView saveWebView11 = new WebView
            {
                Width = Width,
                Height = Height
            };
            TopGrid.Children.Add(saveWebView11);
            WebView saveWebView12 = new WebView
            {
                Width = Width,
                Height = Height
            };
            TopGrid.Children.Add(saveWebView12);
            WebView saveWebView13 = new WebView
            {
                Width = Width,
                Height = Height
            };
            TopGrid.Children.Add(saveWebView13);
            WebView saveWebView14 = new WebView
            {
                Width = Width,
                Height = Height
            };
            TopGrid.Children.Add(saveWebView14);
            WebView saveWebView15 = new WebView
            {
                Width = Width,
                Height = Height
            };
            TopGrid.Children.Add(saveWebView15);
            List<Task> tasks = new List<Task>();
            Task t0 = Task.Run(async () =>
            {
                for (var j=0; j<urls.Count; j=j+16)
                    await ProcessURLHD0Async(urls[j], j, Width, Height, firstFrameSize, saveWebView0, outputFolder);
            });
            tasks.Add(t0);
            Task t1 = Task.Run(async () =>
            {
                for (var j = 1; j < urls.Count; j = j + 16)
                    await ProcessURLHD0Async(urls[j], j, Width, Height, firstFrameSize, saveWebView0, outputFolder);
            });
            tasks.Add(t1);
            Task t2 = Task.Run(async () =>
            {
                for (var j = 2; j < urls.Count; j = j + 16)
                    await ProcessURLHD0Async(urls[j], j, Width, Height, firstFrameSize, saveWebView0, outputFolder);
            });
            tasks.Add(t2);
            Task t3 = Task.Run(async () =>
            {
                for (var j = 3; j < urls.Count; j = j + 16)
                    await ProcessURLHD0Async(urls[j], j, Width, Height, firstFrameSize, saveWebView0, outputFolder);
            });
            tasks.Add(t3);
            Task t4 = Task.Run(async () =>
            {
                for (var j = 4; j < urls.Count; j = j + 16)
                    await ProcessURLHD0Async(urls[j], j, Width, Height, firstFrameSize, saveWebView0, outputFolder);
            });
            tasks.Add(t4);
            Task t5 = Task.Run(async () =>
            {
                for (var j = 5; j < urls.Count; j = j + 16)
                    await ProcessURLHD0Async(urls[j], j, Width, Height, firstFrameSize, saveWebView0, outputFolder);
            });
            tasks.Add(t5);
            Task t6 = Task.Run(async () =>
            {
                for (var j = 6; j < urls.Count; j = j + 16)
                    await ProcessURLHD0Async(urls[j], j, Width, Height, firstFrameSize, saveWebView0, outputFolder);
            });
            tasks.Add(t6);
            Task t7 = Task.Run(async () =>
            {
                for (var j = 7; j < urls.Count; j = j + 16)
                    await ProcessURLHD0Async(urls[j], j, Width, Height, firstFrameSize, saveWebView0, outputFolder);
            });
            tasks.Add(t7);
            Task t8 = Task.Run(async () =>
            {
                for (var j = 8; j < urls.Count; j = j + 16)
                    await ProcessURLHD0Async(urls[j], j, Width, Height, firstFrameSize, saveWebView0, outputFolder);
            });
            tasks.Add(t8);
            Task t9 = Task.Run(async () =>
            {
                for (var j = 9; j < urls.Count; j = j + 16)
                    await ProcessURLHD0Async(urls[j], j, Width, Height, firstFrameSize, saveWebView0, outputFolder);
            });
            tasks.Add(t9);
            Task t10 = Task.Run(async () =>
            {
                for (var j = 10; j < urls.Count; j = j + 16)
                    await ProcessURLHD0Async(urls[j], j, Width, Height, firstFrameSize, saveWebView0, outputFolder);
            });
            tasks.Add(t10);
            Task t11 = Task.Run(async () =>
            {
                for (var j = 11; j < urls.Count; j = j + 16)
                    await ProcessURLHD0Async(urls[j], j, Width, Height, firstFrameSize, saveWebView0, outputFolder);
            });
            tasks.Add(t11);
            Task t12 = Task.Run(async () =>
            {
                for (var j = 12; j < urls.Count; j = j + 16)
                    await ProcessURLHD0Async(urls[j], j, Width, Height, firstFrameSize, saveWebView0, outputFolder);
            });
            tasks.Add(t12);
            Task t13 = Task.Run(async () =>
            {
                for (var j = 13; j < urls.Count; j = j + 16)
                    await ProcessURLHD0Async(urls[j], j, Width, Height, firstFrameSize, saveWebView0, outputFolder);
            });
            tasks.Add(t13);
            Task t14 = Task.Run(async () =>
            {
                for (var j = 14; j < urls.Count; j = j + 16)
                    await ProcessURLHD0Async(urls[j], j, Width, Height, firstFrameSize, saveWebView0, outputFolder);
            });
            tasks.Add(t14);
            Task t15 = Task.Run(async () =>
            {
                for (var j = 15; j < urls.Count; j = j + 16)
                    await ProcessURLHD0Async(urls[j], j, Width, Height, firstFrameSize, saveWebView0, outputFolder);
            });
            tasks.Add(t15);

            await Task.WhenAll(tasks);
        }

public static async Task ProcessURLHD0Async(string url, int i, int width, int height, ulong firstFrameSize, WebView saveWeb, StorageFolder folder)
        {
            try
            {
                var dispatcher = CoreApplication.MainView.CoreWindow.Dispatcher;
                await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                {
                    saveWeb.NavigateToString(url);
                });


                await Task.Delay(3000);
                var kk = 0;
                var pixelised = true;

                while (pixelised == true)
                {
                    ulong thissize = await CaptureAndSave(saveWeb, i, folder);
                    if ((thissize > 0.7 * firstFrameSize) || kk > 5)
                    {
                        pixelised = false;
                    }
                    else
                    {
                        await Task.Delay(1000);
                        kk = kk + 1;
                    }
                }

            }
            catch (Exception)
            {
                throw;
            }
        }

 public static async Task<ulong> CaptureAndSave(WebView webv, int i, StorageFolder folder)
        {
            ulong size = 0;
            SoftwareBitmap softwareBitmap = null;
            InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream();
            BitmapDecoder decoder = null;
            // Changes to imageElement must happen on the UI thread.
            await webv.Dispatcher.RunTaskAsync(async () =>
            {              
                await webv.CapturePreviewToStreamAsync(stream);
                decoder = await BitmapDecoder.CreateAsync(stream);
                softwareBitmap = await decoder.GetSoftwareBitmapAsync();
            });

                StorageFile file_Save = await folder.CreateFileAsync(i + ".jpg", CreationCollisionOption.ReplaceExisting);
                if (file_Save != null)
                {
                    using (var streamF = await file_Save.OpenAsync(FileAccessMode.ReadWrite))
                    {
                        //StorageFile file_Save = await outputFolder.CreateFileAsync(i + "_" + equals + "_" + size + ".jpg", CreationCollisionOption.ReplaceExisting);
                        //< encoder to save > 
                        BitmapEncoder encoder = await BitmapEncoder.CreateAsync(Windows.Graphics.Imaging.BitmapEncoder.JpegEncoderId, streamF);
                        encoder.SetSoftwareBitmap(softwareBitmap);
                        await encoder.FlushAsync();
                        //</ encoder to save > 
                        //-</ Save Bitmap as File >-   
                    }
                }
                var basicProperties = await file_Save.GetBasicPropertiesAsync();
                size = basicProperties.Size;
                while (size < 21)
                {
                    await Task.Delay(100);
                    basicProperties = await file_Save.GetBasicPropertiesAsync();
                    size = basicProperties.Size;
                }
                stream.Dispose();
                softwareBitmap.Dispose();


            return size;
        }

结果:在20秒内捕获118次(总计= 139Mo),在没有并行的情况下捕获278次!最大使用5 GB的ram。

编辑2: 要快...上面的代码有错误,我总是使用Savewebview0,当我更正(Savewebview1,Savewebview2 ....)时结果是... 400秒... 所有的工作都是由主线程完成的,我认为,我需要在其他线程中创建webview,但我认为这是不可能的...... 如果有人有想法...... :(

1 个答案:

答案 0 :(得分:0)

好的,经过多次试验,我的结果很好。

此处的代码适用于想要使用它的人:

public static class DispatcherTaskExtensions
    {
        public static async Task<T> RunTaskAsync<T>(this CoreDispatcher dispatcher,
            Func<Task<T>> func, CoreDispatcherPriority priority = CoreDispatcherPriority.Normal)
        {
            var taskCompletionSource = new TaskCompletionSource<T>();
            await dispatcher.RunAsync(priority, async () =>
            {
                try
                {
                    taskCompletionSource.SetResult(await func());
                }
                catch (Exception ex)
                {
                    taskCompletionSource.SetException(ex);
                }
            });
            return await taskCompletionSource.Task;
        }

        // There is no TaskCompletionSource<void> so we use a bool that we throw away.
        public static async Task RunTaskAsync(this CoreDispatcher dispatcher,
            Func<Task> func, CoreDispatcherPriority priority = CoreDispatcherPriority.Normal) =>
            await RunTaskAsync(dispatcher, async () => { await func(); return false; }, priority);
    }

以上代码在命名空间扩展下面。

    private async void GetHDMT2_Click(object sender, RoutedEventArgs e)
    {
        if (outputFolder == null)
        {
            var folderPicker = new Windows.Storage.Pickers.FolderPicker();
            folderPicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.Desktop;
            folderPicker.FileTypeFilter.Add("*");

            outputFolder = await folderPicker.PickSingleFolderAsync();
            if (outputFolder != null)
            {
                Windows.Storage.AccessCache.StorageApplicationPermissions.
                FutureAccessList.AddOrReplace("PickedFolderToken", outputFolder);
            }
            else
            {
            }
        }
        if (mylat.Count > 0)
        {
            await GetImagesAsyncHD2();
        }
    }

    private async Task GetImagesAsyncHD2()
    {
        // Make a dictionary with html code string (with street view iframe inside .
        var Width = 4000;
        var Height = 2000;
        Dictionary<int,string> urls = SetUpURLListHD(Width, Height);

        //Code to estimate time for completely loading the first page (compute a time to use in await task.delay, and the size of first frame nextly used to know if image is pixelised or not (street view fisnish loading or not)
        SoftwareBitmap softwareBitmap = null;
        InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream();
        BitmapDecoder decoder = null;
        var k = 0;
        WebView saveWebView = new WebView();
        saveWebView.Width = Width;
        saveWebView.Height = Height;
        TopGrid.Children.Add(saveWebView);
        var stopwatch = new Stopwatch();
        stopwatch.Start();
        long elapsed_time=0;
        saveWebView.NavigateToString(urls[0]);
        await Task.Delay(10);
        bool equals = false;
        bool findeq = false;
        int t = 0;
        int countTrue = 0;
        bool checka = false;
        List<byte[]> bytes400a = null;
        List<byte[]> bytes400b = null;
        await saveWebView.CapturePreviewToStreamAsync(stream);
        decoder = await BitmapDecoder.CreateAsync(stream);
        softwareBitmap = await decoder.GetSoftwareBitmapAsync();
        bytes400a = GetPixelsP(softwareBitmap);
        while (countTrue < 20)
        {
            await Task.Delay(50);
            if (checka)
            {
                await saveWebView.CapturePreviewToStreamAsync(stream);
                decoder = await BitmapDecoder.CreateAsync(stream);
                softwareBitmap = await decoder.GetSoftwareBitmapAsync();
                bytes400a = GetPixelsP(softwareBitmap);
                checka = false;
            }
            else
            {
                await saveWebView.CapturePreviewToStreamAsync(stream);
                decoder = await BitmapDecoder.CreateAsync(stream);
                softwareBitmap = await decoder.GetSoftwareBitmapAsync();
                bytes400b = GetPixelsP(softwareBitmap);
                checka = true;
            }
            t = t + 1;
            equals = EqualsByte(bytes400a, bytes400b);
            if (equals)
            {
                countTrue = countTrue + 1;
            }
            if ((equals) && (findeq == false))
            {
                k = t;
                elapsed_time = stopwatch.ElapsedMilliseconds;
                SlidetimeCompute.Value = elapsed_time;
                findeq = true;
            }
            if (equals == false) { findeq = false; }
        }
        stopwatch.Stop();
        var elapsed_timeForTest = stopwatch.ElapsedMilliseconds;
        await SaveSSAsync(softwareBitmap, "0");
        ulong firstFrameSize = await GetSizePicAsync("0");
        TopGrid.Children.Remove(saveWebView);
        stream.Dispose();
        softwareBitmap.Dispose();

        double timeTowait = (double)elapsed_time;
        timeTowait = Math.Round(timeTowait / 4);

        // prepare somes grids
        var nj = 7;
        List<Grid> grids = new List<Grid>();
        Grid tmpgrid0 = new Grid();
        grids.Add(tmpgrid0);
        Grid tmpgrid1 = new Grid();
        grids.Add(tmpgrid1);
        Grid tmpgrid2 = new Grid();
        grids.Add(tmpgrid2);
        Grid tmpgrid3 = new Grid();
        grids.Add(tmpgrid3);
        Grid tmpgrid4 = new Grid();
        grids.Add(tmpgrid4);
        Grid tmpgrid5 = new Grid();
        grids.Add(tmpgrid5);
        Grid tmpgrid6 = new Grid();
        grids.Add(tmpgrid6);
        Grid tmpgrid7 = new Grid();
        grids.Add(tmpgrid7);
        Grid tmpgrid8 = new Grid();
        grids.Add(tmpgrid8);
        Grid tmpgrid9 = new Grid();
        grids.Add(tmpgrid9);
        Grid tmpgrid10 = new Grid();
        grids.Add(tmpgrid10);
        Grid tmpgrid11 = new Grid();
        grids.Add(tmpgrid11);
        Grid tmpgrid12 = new Grid();
        grids.Add(tmpgrid12);
        Grid tmpgrid13 = new Grid();
        grids.Add(tmpgrid13);
        Grid tmpgrid14 = new Grid();
        grids.Add(tmpgrid14);
        Grid tmpgrid15 = new Grid();
        grids.Add(tmpgrid15);
        Grid tmpgrid16 = new Grid();
        grids.Add(tmpgrid16);

        // add tasks
        List<Task> tasks = new List<Task>();
        for (var i = 1; i < nj+1; i++)
        {
            TopGrid.Children.Add(grids[i]);
            await Task.Delay(1000);
            tasks.Add(await AddTaskAsync(i, nj, Width, Height, firstFrameSize,outputFolder, grids[i], urls, timeTowait)
                );
        }
        // await all tasks
        await Task.WhenAll(tasks);
    }

    public static async Task<Task> AddTaskAsync(int i, int nj, int width, int height, ulong firstFrameSize, StorageFolder folder, Grid grid, Dictionary<int, string> urls, double timeTowait)
    {
        var t0 = Task.Run(async () =>
        {
            for (var j = i; j < urls.Count; j = j + nj)
                await ProcessURLHD1Async(urls[j], j, width, height, firstFrameSize, folder, grid, timeTowait);
        });
        await Task.Delay(200);
        return t0;
    }

    public static async Task ProcessURLHD1Async(string url, int i, int width, int height, ulong firstFrameSize, StorageFolder folder, Grid grid, double timeTowait)
    {
        try
        {
            var Dispatcher = CoreApplication.MainView.CoreWindow.Dispatcher;
            await grid.Dispatcher.RunTaskAsync(async () =>
            {
                var saveWeb1 = new WebView(WebViewExecutionMode.SeparateThread)
                {
                    Width = width,
                    Height = height
                };
                grid.Children.Add(saveWeb1);
                saveWeb1.NavigateToString(url);
                //give street view some delay to load
                await Task.Delay((int)timeTowait*5);
                var kk = 0;
                var pixelised = true;
                SoftwareBitmap softwareBitmap = null;
                InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream();
                BitmapDecoder decoder = null;

                while (pixelised == true)
                {
                    await saveWeb1.CapturePreviewToStreamAsync(stream);
                    decoder = await BitmapDecoder.CreateAsync(stream);
                    softwareBitmap = await decoder.GetSoftwareBitmapAsync();


                    StorageFile file_Save = await folder.CreateFileAsync(i + ".jpg", CreationCollisionOption.ReplaceExisting);
                    if (file_Save != null)
                    {
                        using (var streamF = await file_Save.OpenAsync(FileAccessMode.ReadWrite))
                        {
                            BitmapEncoder encoder = await BitmapEncoder.CreateAsync(Windows.Graphics.Imaging.BitmapEncoder.JpegEncoderId, streamF);
                            encoder.SetSoftwareBitmap(softwareBitmap);
                            await encoder.FlushAsync();
                        }
                    }
                    var basicProperties = await file_Save.GetBasicPropertiesAsync();
                    ulong thissize = basicProperties.Size;
                    while (thissize < 21)
                    {
                        await Task.Delay(100);
                        basicProperties = await file_Save.GetBasicPropertiesAsync();
                        thissize = basicProperties.Size;
                    }

                    if ((thissize > 0.7 * firstFrameSize) || kk > 10)
                    {
                        pixelised = false;
                    }
                    else
                    {
                        await Task.Delay((int)timeTowait*2);
                        kk = kk + 1;
                    }
                }
                stream.Dispose();
                softwareBitmap.Dispose();
                grid.Children.Clear();

            });
        }
        catch (Exception)
        {
            throw;
        }
    }

最佳结果是并行执行7项任务。为什么7?不知道。 使用单个任务,118秒捕获(141 Mo),7个任务58秒! 现在,我需要找到一种方法来使代码适应不同的硬件和互联网连接。