我正在学习代码并做一个捕获谷歌街景截屏的应用程序。很多截图。我想找到一种并行查询的方法。
这里是单个查询的代码:
// 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,但我认为这是不可能的...... 如果有人有想法...... :(
答案 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秒! 现在,我需要找到一种方法来使代码适应不同的硬件和互联网连接。