RSS Reader in javafx - rss

I'm trying parse a rss feed from javafx project, but i'm getting the following exception,
java.lang.NullPointerException
at com.sun.webpane.webkit.network.CookieJar$PolicyDelegateFilter.shouldAccept(CookieJar.java:42)
at com.sun.webpane.webkit.network.CookieManager.put(CookieManager.java:193)
at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:710)
at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:632)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1049)
at java.net.URL.openStream(URL.java:1009)
at org.jugc.rss.RSSReader.readNews(RSSReader.java:38)
at org.jugc.view.RSSViewer.(RSSViewer.java:34)
at org.jugc.view.JugCMain.start(JugCMain.java:67)
at com.sun.javafx.application.LauncherImpl$3.run(LauncherImpl.java:127)
at com.sun.javafx.application.PlatformImpl$3.run(PlatformImpl.java:87)
at com.sun.javafx.application.PlatformImpl$2.run(PlatformImpl.java:65)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.access$100(WinApplication.java:29)
at com.sun.glass.ui.win.WinApplication$1$1.run(WinApplication.java:49)
at java.lang.Thread.run(Thread.java:619)
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
URL u = new URL("http://www.jugchennai.in/feed/"); // your feed url
System.setProperty("http.proxyHost", "192.168.32.10");
System.setProperty("http.proxyPort", "8080");
Document doc = builder.parse(u.openStream());
NodeList nodes = doc.getElementsByTagName("item");
for (int i = 0; i < nodes.getLength(); i++) {
Element element = (Element) nodes.item(i);
RSSFeed rSSFeed = new RSSFeed();
rSSFeed.setTitle(getElementValue(element, "title"));
rSSFeed.setLink(getElementValue(element, "link"));
rSSFeed.setPublishDate(getElementValue(element, "pubDate"));
rSSFeed.setAuthor(getElementValue(element, "dc:creator"));
rSSFeed.setDescripition(getElementValue(element, "description"));
rssFeeds.add(rSSFeed);
}
I'm using following code in javafx
RSSReader rSSReader = RSSReader.getInstance();
ArrayList<RSSFeed> rSSFeeds = (ArrayList) rSSReader.readNews();
//ArrayList<RSSFeed> rSSFeeds = new ArrayList<RSSFeed>();
RSSFeed rSSFeed1 = new RSSFeed();
rSSFeed1.setTitle("August Meetup Scalatra, Scalate Netbeans Training");
rSSFeed1.setLink("http://www.jugchennai.in/2011/08/13/august-meetup-scalatra-scalate-netbeans-training/");
rSSFeeds.add(rSSFeed1);
Hyperlink[] hpls = new Hyperlink[rSSFeeds.size()];
for (int i = 0; i < rSSFeeds.size(); i++) {
RSSFeed rSSFeed = rSSFeeds.get(i);
final Hyperlink hpl = hpls[i] = new Hyperlink(rSSFeed.getTitle());
final String url = rSSFeed.getLink();
hpl.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
webEngine.load(url);
}
});
}
toolBar = new VBox();
toolBar.setVisible(true);
toolBar.getChildren().addAll(hpls);
getChildren().add(toolBar);
getChildren().add(browser);

Related

unity 2d auto shadow caster 2d at wall-closed tilemap

https://www.youtube.com/watch?v=0F8boyFinOk&t=12s
While making a roguelike game with Unity2d, I applied an automatic shadow generator to a randomly generated tilemap from the video above. But it doesn't work for tilemaps that are closed due to using the CompositeCollider2d's Path. How do I solve it?
Generated Shadow Shape(outer)
Generated Shadow Shape(inner)
Solved with this code:
using System.Linq;
using System.Reflection;
using UnityEngine;
using UnityEngine.Rendering.Universal;
using System.Collections.Generic;
[RequireComponent(typeof(CompositeCollider2D))]
public class AutoShadowClosedTilemap : MonoBehaviour
{
[Space]
[SerializeField]
private bool selfShadows = true;
private CompositeCollider2D tilemapCollider;
private List<Vector2> unionVertices = new();
static readonly FieldInfo meshField = typeof(ShadowCaster2D).GetField("m_Mesh", BindingFlags.NonPublic | BindingFlags.Instance);
static readonly FieldInfo shapePathField = typeof(ShadowCaster2D).GetField("m_ShapePath", BindingFlags.NonPublic | BindingFlags.Instance);
static readonly MethodInfo generateShadowMeshMethod = typeof(ShadowCaster2D)
.Assembly
.GetType("UnityEngine.Rendering.Universal.ShadowUtility")
.GetMethod("GenerateShadowMesh", BindingFlags.Public | BindingFlags.Static);
[ContextMenu("Generate")]
public void Generate()
{
tilemapCollider = GetComponent<CompositeCollider2D>();
if(tilemapCollider.pathCount != 2) {
print("Shadow must be used in one closed tiles. Please erase the other tiles to other Tilemap.");
return;
}
unionVertices.Clear();
DestroyAllChildren();
Vector2[] pathVertices = new Vector2[tilemapCollider.GetPathPointCount(0)];
tilemapCollider.GetPath(0, unionVertices);
tilemapCollider.GetPath(1, pathVertices);
var index = 0;
var endPath = unionVertices[unionVertices.Count - 1];
var length = Vector2.Distance(pathVertices[0], endPath);
for(var i = 1; i < pathVertices.Length; i++) {
var path = pathVertices[i];
var curLen = Vector2.Distance(endPath, path);
if(curLen < length) {
length = curLen;
index = i;
}
}
for(var i = 0; i < pathVertices.Length; i++) {
var path = pathVertices[(i + index) % pathVertices.Length];
unionVertices.Add(path);
}
for(var i = 0; i < unionVertices.Count; i++) {
var cur = unionVertices[i];
var next = unionVertices[(i + 1) % unionVertices.Count];
Debug.DrawLine(cur, cur + (next - cur) * 0.5f, Color.red);
}
var shadowCaster = new GameObject("ShadowCaster");
shadowCaster.transform.parent = gameObject.transform;
shadowCaster.transform.position = Vector3.zero;
ShadowCaster2D shadowCasterComponent = shadowCaster.AddComponent<ShadowCaster2D>();
shadowCasterComponent.selfShadows = this.selfShadows;
var testPath = new Vector3[unionVertices.Count];
var j = 0;
foreach (var path in unionVertices)
{
testPath[j++] = path;
}
shapePathField.SetValue(shadowCasterComponent, testPath);
meshField.SetValue(shadowCasterComponent, new Mesh());
generateShadowMeshMethod.Invoke(shadowCasterComponent, new object[] { meshField.GetValue(shadowCasterComponent), shapePathField.GetValue(shadowCasterComponent) });
Debug.Log("Shadow Generated");
}
public void DestroyAllChildren()
{
var tempList = transform.Cast<Transform>().ToList();
foreach (var child in tempList)
{
DestroyImmediate(child.gameObject);
}
}
}

Xamarin Maps on android custom pins query

I am working on a xamarin forms app using xamarin forms maps for Android at the moment that tracks my location and depending on my proximity to a custom pin i have placed on the map will change in size depending on my proximity.
Basically if within a few meters the icon is 32x32 and farther away its 24x24.
Ive created a custom map renderer that places my pins from a JSON file and this is ok.
When my map form page loads in both my simulator and an actual android device the methods run and get my proximity based on my location and appropriately alter the size of the map pin.
However, this does not work as i move around.
For some reason my overridden CreateMarker method does not trigger when my location changes unless i call Content=customMap. Doing this only causes my map to load over and over and basically will not work.
I have a method in my about page called UpdateMap3() that is called when the users location changes. However, as stated i cant get the pins to update their size as i get nearer the pins while the app is running.
Ive included my forms page code behind below and markup below that and finally my map renderer below that.
Any help would be hugely appreciated.
Thanls
using System;
using System.IO;
using System.Reflection;
using Xamarin.Forms;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using Xamarin.Forms.Maps;
using Xamarin.Essentials;
using Distance = Xamarin.Forms.Maps.Distance;
using Google.Protobuf.WellKnownTypes;
using static Google.Protobuf.Reflection.FieldDescriptorProto.Types;
namespace MAPS.Views
{
public partial class AboutPage : ContentPage
{
IlocationUpdateService loc;
public AboutPage()
{
InitializeComponent();
// Task.Delay(2000);
UpdateMap();
}
async void OnActionSheetCancelDeleteClicked()
{
bool answer = await DisplayAlert("Location Request", "Please enable location services to use this app", "Settings", "Cancel");
if (answer == true)
{
DependencyService.Get<ILocSettings>().OpenSettings();
}
}
protected override void OnAppearing()
{
base.OnAppearing();
bool gpsStat = DependencyService.Get<ILocSettings>().isGpsAvailable();
if (gpsStat == false)
{
OnActionSheetCancelDeleteClicked();
}
loc = DependencyService.Get<IlocationUpdateService>();
loc.LocationChanged += (object sender, ILocationEventArgs args) =>
{
String lat1 = args.Latitude.ToString();
String lng1 = args.Longitude.ToString();
//String lat1 = "55.099300";
// String lng1 = "-8.279740";
UpdateMap3(lat1, lng1); ;
};
loc.GetUsedLocation();
}
protected override void OnDisappearing()
{
base.OnDisappearing();
loc = null;
}
List<Place> placesList = new List<Place>();
private async void UpdateMap()
{
var assembly = IntrospectionExtensions.GetTypeInfo(typeof(AboutPage)).Assembly;
Stream stream = assembly.GetManifestResourceStream("MAPS.Places.json");
string text = string.Empty;
using (var reader = new StreamReader(stream))
{
text = reader.ReadToEnd();
}
var resultObject = JsonConvert.DeserializeObject<Places>(text);
var request = new Xamarin.Essentials.GeolocationRequest(GeolocationAccuracy.Best, TimeSpan.FromSeconds(30));
var location = await Geolocation.GetLocationAsync(request);
CustomMap customMap = new CustomMap()
{
IsShowingUser = true
};
customMap.CustomPins = new List<CustomPin>(); // put this before the foreach
foreach (var place in resultObject.results)
{
Location location1 = new Location(place.geometry.location.lat,place.geometry.location.lng);
// string color = getDist(location1, location);
string color = "purple";
if (color == "purple")
{
CustomPin pin = new CustomPin()
{
Type = PinType.Place,
Position = new Position(place.geometry.location.lat, place.geometry.location.lng),
Label = place.id,
Address = place.vicinity+"*",
Name = "Xamarin",
icon = "icon.png",
Url = "http://xamarin.com/about/"
};
customMap.Pins.Add(pin);
}
else
{
CustomPin pin = new CustomPin()
{
Type = PinType.Place,
Position = new Position(place.geometry.location.lat, place.geometry.location.lng),
Label = place.id,
Address = place.vicinity,
Name = "Xamarin",
icon = "pin.png",
Url = "http://xamarin.com/about/"
};
customMap.Pins.Add(pin);
}
}
customMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(location.Latitude, location.Longitude), Distance.FromKilometers(0.15))); ;
Content = customMap;
}
public string getDist(Location loc, Xamarin.Essentials.Location currentLoc)
{
string color = "red";
// bool geo = false;
double latEnd = loc.lat;
double lngEnd = loc.lng;
/// Position(currentLoc.lat, currentLoc.lng);
double dist = currentLoc.CalculateDistance(latEnd, lngEnd, DistanceUnits.Kilometers);
if (dist < 0.05) //5m distance
{
color = "purple";
}
else
{
color = "red";
}
return color;
}
public void getNewPins()
{
InitializeComponent();
}
public void getPin()
{
var pr = new PopUp();
}
private async void UpdateMap3(String lat, String lng)
{
var assembly = IntrospectionExtensions.GetTypeInfo(typeof(AboutPage)).Assembly;
Stream stream = assembly.GetManifestResourceStream("MAPS.Places.json");
string text = string.Empty;
using (var reader = new StreamReader(stream))
{
text = reader.ReadToEnd();
}
var resultObject = JsonConvert.DeserializeObject<Places>(text);
CustomMap customMap = new CustomMap()
{
IsShowingUser = true
};
customMap.CustomPins = new List<CustomPin>(); // put this before the foreach
foreach (var place in resultObject.results)
{
Location location1 = new Location(place.geometry.location.lat, place.geometry.location.lng);
Xamarin.Essentials.Location location = new Xamarin.Essentials.Location(Convert.ToDouble(lat), Convert.ToDouble(lng));
string color = getDist(location1, location);
if (color == "purple")
{
CustomPin pin2 = new CustomPin()
{
Type = PinType.Place,
Position = new Position(place.geometry.location.lat, place.geometry.location.lng),
Label = place.id,
Address = place.vicinity,
Name = "Xamarin",
icon = "icon.png",
Url = "http://xamarin.com/about/"
};
customMap.CustomPins = new List<CustomPin> {pin2};
customMap.Pins.Add(pin2);
}
else
{
CustomPin pin2 = new CustomPin()
{
Type = PinType.Place,
Position = new Position(place.geometry.location.lat, place.geometry.location.lng),
Label = place.id,
Address = place.vicinity+"*",
Name = "Xamarin",
icon = "pin.png",
Url = "http://xamarin.com/about/"
};
customMap.CustomPins = new List<CustomPin> { pin2 };
customMap.Pins.Add(pin2);
// Content.IsEnabled = true;
// customMap.CustomPins.Remove(pin);
}
}
// customMap.Pins.Clear();
// customMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(Convert.ToDouble(lat), Convert.ToDouble(lng)), Distance.FromKilometers(0.15))); ;
// Content = customMap;
// customMap.Pins.Add(pins);
}
}
}
Below is my forms page markup.
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MAPS;assembly=MAPS"
x:Class="MAPS.Views.AboutPage" Title="Explore">
<StackLayout>
<local:CustomMap x:Name="customMap" IsShowingUser="True"
MapType="Street" />
</StackLayout>
</ContentPage>
Below is my Android custom renderer
using Android.Content;
using Android.Gms.Maps;
using Android.Gms.Maps.Model;
using Android.Widget;
using MAPS;
using MAPS.Droid;
using MAPS.Views;
using Newtonsoft.Json;
using Rg.Plugins.Popup;
using Rg.Plugins.Popup.Animations;
using Rg.Plugins.Popup.Contracts;
using Rg.Plugins.Popup.Enums;
using Rg.Plugins.Popup.Services;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Xamarin.Forms;
using Xamarin.Forms.Maps;
using Xamarin.Forms.Maps.Android;
using static MAPS.Droid.CustomMapRenderer;
[assembly: ExportRenderer(typeof(CustomMap), typeof(CustomMapRenderer))]
namespace MAPS.Droid
{
public class CustomMapRenderer : Xamarin.Forms.Maps.Android.MapRenderer, GoogleMap.IInfoWindowAdapter
{
List<CustomPin> customPins;
public string popInfo;
public CustomMapRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs<Map> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
NativeMap.InfoWindowClick -= OnInfoWindowClick;
}
if (e.NewElement != null)
{
var formsMap = (CustomMap)e.NewElement;
customPins = formsMap.CustomPins;
Control.GetMapAsync(this);
}
}
protected override void OnMapReady(GoogleMap map)
{
base.OnMapReady(map);
NativeMap.InfoWindowClick += OnInfoWindowClick;
NativeMap.SetInfoWindowAdapter(this);
}
protected override MarkerOptions CreateMarker(Pin pin)
{
var marker = new MarkerOptions();
// CustomPin p = new CustomPin();
//foreach (var cp in customPins)
//{
// if (cp.Position == pin.Position)
// {
// p = cp;
// }
//}
marker.SetPosition(new LatLng(pin.Position.Latitude, pin.Position.Longitude));
marker.SetTitle(pin.Label);
// marker.SetIcon(BitmapDescriptorFactory.FromFile(p.icon));
if (pin.Address.Contains('*'))
{
marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.pin2));
}
else
{
marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.pin));
}
marker.Visible(true);
var a = NativeMap.AddMarker(marker);
a.ShowInfoWindow();
// marker.SetSnippet(pin.Address.Replace("*", " "));
return marker;
}
void OnInfoWindowClick(object sender, GoogleMap.InfoWindowClickEventArgs e)
{
getPlaceData(markerdata.markerData.title, markerdata.markerData.lat, markerdata.markerData.lng);
showPopUp();
}
public Android.Views.View GetInfoContents(Marker marker)
{
return null;
}
public void myMod(Marker marker)
{
}
public Android.Views.View GetInfoWindow(Marker marker)
{
markerdata.markerData.title = marker.Title;
markerdata.markerData.lat = marker.Position.Latitude.ToString("0.#####");
markerdata.markerData.lng = marker.Position.Longitude.ToString("0.#####");
// ds.Id = marker.Id;
// getPlaceData(marker.Title, marker.Position.Latitude.ToString("0.#####"), marker.Position.Longitude.ToString("0.#####"));
// showPopUp();
return null;
}
public string Number;
private async void showPopUp()
{
var Pr = new Views.PopUp();
var scaleAnimation = new ScaleAnimation
{
PositionIn = MoveAnimationOptions.Right,
PositionOut = MoveAnimationOptions.Left
};
Pr.Animation = scaleAnimation;
await PopupNavigation.PushAsync(Pr);
}
CustomPin GetCustomPin(Marker annotation)
{
return null;
}
private void getPlaceData(String name, String Lat, String Lng)
{
var assembly = IntrospectionExtensions.GetTypeInfo(typeof(AboutPage)).Assembly;
Stream stream = assembly.GetManifestResourceStream("MAPS.Places.json");
string text = string.Empty;
using (var reader = new StreamReader(stream))
{
text = reader.ReadToEnd();
}
var resultObject = JsonConvert.DeserializeObject<Places>(text);
foreach (var place in resultObject.results)
{
if((name==place.id)&&(Lat ==place.geometry.location.lat.ToString("0.#####"))&&(Lng ==place.geometry.location.lng.ToString("0.#####")))
{
getData.Instance.Id = place.id;
getData.Instance.lat = place.geometry.location.lat.ToString("0.#####");
getData.Instance.lng = place.geometry.location.lng.ToString("0.#####");
getData.Instance.marker2 = place.name;
getData.Instance.family = place.family;
getData.Instance.origin = place.Origin;
getData.Instance.date = place.Date;
getData.Instance.commonName = place.CommonName;
// getData.Instance.title = marker.Title;
}
}
}
}
}

Dispose own created Tab

Hi I have upgrade my application from 45 to Cefsharp version 71,Earlier new created tab is easily dispose(remove) but now the whole application is shut down,When i am using remove method the tab is closed but it remain in the memory that cause system hanged.
public void AddNewBrowserTab(string url, int? insertIndex = null) {
browserTabControl.SuspendLayout();
var browser = new BrowserTabUserControl(AddNewBrowserTab, url, UserName, pass, browserTabControl, txtUName.Text.ToString().Trim(), txtUPassword.Text.ToString().Trim(), MUser, TUser);
var tabPage = new TabPage(url);
browser.CreateControl();
tabPage.Controls.Add(browser);
if (insertIndex == null) {
browserTabControl.TabPages.Add(tabPage);
} else {
browserTabControl.TabPages.Insert(insertIndex.Value, tabPage);
}
browserTabControl.SelectedTab = tabPage;
browserTabControl.ResumeLayout(true);
}
//Call Method
public BrowserTabUserControl(Action<string, int?> openNewTab, string url, string uname, string pwd, TabControl browserTabControl, string loginUsrname, string LoginUsrpwd, string muser, string thuser) {
InitializeComponent();
MonsterUsr = monsteruser;
Techfetchuser = techfetchuser;
loginUsername = loginUsrname;
name = uname;
passwd = pwd;
txtuname = loginUsrname;
txtupwd = LoginUsrpwd;
browserTabControls = browserTabControl;
var browser = new ChromiumWebBrowser(url) {
Dock = DockStyle.Fill
};
var userControl = new UserControl { Dock = DockStyle.Fill };
ZoomIn.Controls.Add(browser);
Browser = browser;
browser.MenuHandler = new MenuHandler();
browser.JsDialogHandler = new JsDialogHandler();
browser.AddressChanged += Browser_AddressChanged;
browser.DownloadHandler = new DownloadHandler(browserTabControl);
browser.LifeSpanHandler = new LifeSpanHandler(browserTabControl, ref Browser, loginUsrname, LoginUsrpwd);
browser.KeyboardHandler = new KeyboardHandler();
}

Fill JavaFX combobox by javascript class (Nashorn)

I try to use my custom class which I have created in my script (the script is written in Nashorn) and after that I try to use this custom class to fill in as items in combobox. I know that if I want to see correct values in combobox that the class has to override method toString, but in this case I do not know much how can be overriden this method in my custom class written in Nahorn.
Below I provide my code where the variables cmbCategories is JavaFX combobox and CategoryItem which I try to use as object to fill in the items in combobox and display as category name.
I would appreciate any suggestion or ideas how can be this problem resolved.
var ClientBuilder = Java.type("javax.ws.rs.client.ClientBuilder")
var Platform = Java.type("javafx.application.Platform")
var Executors = Java.type("java.util.concurrent.Executors")
var Response = Java.type("javax.ws.rs.core.Response")
var String = Java.type("java.lang.String")
var List = Java.type("java.util.ArrayList")
Executors.newSingleThreadExecutor().execute(function () {
print("Calling for category data...")
var categoryData = ClientBuilder
.newClient()
.target(String.format("%s%s", "http://localhost:8080", "/client/action/categories"))
.request()
.get()
if(categoryData.getStatus() == Response.Status.OK.getStatusCode()) {
var categories = JSON.parse(categoryData.readEntity(String.class))
var categoryItems = new List();
for each (var category in categories) {
categoryItems.add(new CategoryItem(category.id, category.category))
}
Platform.runLater(function() {
cmbCategory.getItems().addAll(categoryItems);
});
} else {
print(categoryData.getEntity().toString());
}
})
function CategoryItem(id, name) {
this.id = id;
this.name = name;
this.toString = function () {
return this.name;
}
}
Use the ScriptEngine to retrieve an appropriate string in the cellValueFactory of the ComboBox.
Simplified example
#Override
public void start(Stage primaryStage) throws Exception {
ScriptEngineManager manager = new ScriptEngineManager();
final ScriptEngine engine = manager.getEngineByMimeType("application/javascript");
ComboBox<Object> comboBox = new ComboBox();
comboBox.setCellFactory(c -> new ListCell<Object>() {
#Override
protected void updateItem(Object item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText("");
} else {
Bindings bindings = new SimpleBindings();
bindings.put("a", item);
try {
// use script engine to retrieve text
setText(Objects.toString(engine.eval("a.name", bindings)));
} catch (ScriptException ex) {
setText("Error");
}
}
}
});
comboBox.setButtonCell(comboBox.getCellFactory().call(null));
Bindings b = new SimpleBindings();
b.put("cmbCategory", comboBox);
engine.eval("function CategoryItem(id, name) {this.id = id;this.name = name;}\n"
+"var Platform = Java.type(\"javafx.application.Platform\")\n"
+ "var categories = [new CategoryItem(1, 'a'), new CategoryItem(2, 'b'), new CategoryItem(3,'c')]\n"
+ "for each (var category in categories) {cmbCategory.getItems().add(category);}", b);
Scene scene = new Scene(new StackPane(comboBox));
primaryStage.setScene(scene);
primaryStage.show();
}
I don't see the purpose of using JavaScript for this though. Everything you do in the javascript code could be done from java code more efficiently...

How to signal waithandle.waitany when doing async requests?

I'm using the following sample code to fetch some HTML Pages using async requests.
I don't want to wait until every request is completed that is using WaitHandle.WaitAll, just until the correct value is found. I'm currently doing it this way, but it feels wrong to send ManualResetEvents to the thread. Is it how it should be done? Is there a better way?
public static void runprogram()
{
System.Net.ServicePointManager.DefaultConnectionLimit = 20;
FetchPageDelegate del = new FetchPageDelegate(FetchPage);
List<HtmlDocument> htmllist = new List<HtmlDocument>();
List<IAsyncResult> results = new List<IAsyncResult>();
List<WaitHandle> waitHandles = new List<WaitHandle>();
List<ManualResetEvent> handles = new List<ManualResetEvent>();
for (int i = 0; i < 20; i++)
{
ManualResetEvent e = new ManualResetEvent(false);
handles.Add(e);
}
for(int i = 0; i < 200; i += 10)
{
int y = 0;
string url = #"URLTOPARSE" + i;
IAsyncResult result = del.BeginInvoke(url, handles[y], null, null);
results.Add(result);
waitHandles.Add(result.AsyncWaitHandle);
y++;
}
//Here i check for a signal
WaitHandle.WaitAny(handles.ToArray());
//WaitHandle.WaitAll(waitHandles.ToArray());
foreach (IAsyncResult async in results)
{
FetchPageDelegate delle = (async as AsyncResult).AsyncDelegate as FetchPageDelegate;
HtmlDocument htm = delle.EndInvoke(async);
if(htm.DocumentNode.InnerHtml.Contains("ANYTHING TO CHECK FOR(ONLY A TEST"))
{
return;
}
}
}

Resources