Browser Wars and Internet Explorer’s Compatibility View issue.

The following story is based on true events... (Hebrew).

“Crisis”: Unlike the different internal presentations, on our customer’s CEO computer, the web application we’ve developed appeared broken, causing poor user experience. For us, the problem was clear and known: the CEO was using IE8 set to Compatibility View.

Proper Development provides outsourcing and consulting services in the .NET development framework for a certain company dealing with security. Amongst other activities, we develop an extensive Web Application designated to be the front-end interface for the different product users. The application is developed in ASP.NET 4, using rich graphics from professional designers, and includes multiple ASP.NET Themes and MS ASP.NET Ajax usage for a better and faster user experience. In advanced stages of the development, towards the oncoming pre-release version, we were called to the CEO’s office, who attempted to use the web application as it was installed on the QA servers, and that’s when the problem occurred - the IE Compatibility View Issue.

In order to understand what Compatibility View is, several words are required in order to understand Web Application development and Browser Wars. Web Application development is inherently different from developing regular desktop applications, as the user is not using a local installed application, but an Internet browser. The user experience depends explicitly on the type and version of the browser used. Usually, the more updated the browser is, the better user experience. But, there had been many changes throughout the years, and the fact that Microsoft’s Internet Explorer was incorporated within Windows helped it become the worlds most dominant browser (at least on PC machines), and had Microsoft try to lead the browser market by developing their own standards, not following the common worldwide standards. This caused many web sites to break on competitor browsers, as they were developed targeting IE only, and a lot of effort had to be invested (time & money), or even postponing product deliveries, in order for the web site to be compatible to both IE and non-IE browsers.

But what seemed to be like a certain victory for Microsoft over the competitors, changed several years back with the arrivals of strong competitors browsers (Firefox, Safari, Google Chrome etc’), which provided a more reasonable solution for the customers growing needs, whereas Microsoft neglected the competition and chose not to develop more advanced versions for IE. A simple example for this would be tabbed-browsing, which wasn’t available till the end of 2006 (in IE7), whereas the competitors had this feature “built in” for years. In the past several years, Microsoft understands that neglecting the users, and standards, was wrong, and is investing a lot of effort to develop more advanced and competitive browsers, which support the world wide standards. We saw this first with the emergence of IE8, which was a major milestone towards implementing the world wide standards (but still, very far from it), and the near coming IE9, which should be a major upgrade, both as far as standards go, as well as performance.

The problem Microsoft was facing, ironically, were exactly those same web sites which were built for years targeting older IE browsers, and not according to world wide standards. Browsing to these websites using IE8 could cause them to break, just like in competitor browsers. As in other cases, Microsoft solved this problem by incorporating a “Compatibility View”, and with a click of a button, an IE8 user can view the currently displayed website as if using IE7, viewing the website correctly.

This was the case for our CEO customer. He was using IE8 which was set to Compatibility View, and actually viewed our application as if he was using IE7. The web application was developed to support IE8 and Firefox 3.5, in order not to spend precious “time to market” development time in making the application IE7-compatible, and that’s why it broke on his machine. With click of a button, we switched back his browser to IE8 view, and the problem was gone. But this didn’t solve the true problem at hand: any user could tackle this exact problem, and accidentally browse using Compatibility View. The common programmable solutions, which suppose to help IE8 understand that it’s supposed to display the website not in Compatibility View - don’t always work, for example in cases where IE8 could be configured so that intranet sites always display in Compatibility View. More over, there are users who actually browse using IE6 or IE7, and their user experience could be quite bad.

The ideal solution was allegedly simple: lets support all the browsers! But this is probably the non-recommended option. The time and effort required to support older browsers, including QA and postponing product releases - is not always worth the effort, except for uncommon scenarios. In a world where browsers constantly become more and more advanced, that leading websites decide to stop older IE support (google, YouTube and Facebook Chat), and that Microsoft recommends to upgrade to IE8 - you have to have a good reason to continue financing support for IE6 or IE7. Over 70% of Internet users don’t use these older versions, as of August 2010.

So, eventually, there were two choices to choose from, concerning older IE users:
  1. Include support for IE7 (there was no intention to support IE6 at all in the case discussed) - this would have impact on development and QA, with more chance for bugs and support later on.
  2. To detect the version of the IE browser, and act accordingly in the following manner:
    1. For IE6/7 - display a message regarding the supported browsers, plus a recommendation to upgrade to those supported browsers (this method is also used for other non-IE browsers which aren’t officially supported).
    2. For IE8, in Compatibility View - display a message explaining what Compatibility View is, including a recommendation to switch it off, including instructions on how to do so.

    In any case, the user can “accept responsibility”, and decide to continue browsing using a non-supported browser.

    It’s important to understand, that supporting IE7 is something that can be added later on, upon customer feedback. You can always decide to support older browsers later on. Also important is the understanding, that supporting certain types of browsers and giving up others, especially IE6/7 which are still common browsers, should be a strategic management-level decision, and not the development team’s call (although the development team should take part in this decision making).

    In our case, the decision was indeed not to support IE7, till possible user feedback will demand such support (if at all), and to display those messages encouraging users to upgrade to IE8 or FF 3.5, or above. If a user browses using Compatibility View, we’ll provide explanation on how to switch back to IE8.

    Read how to programmatically check if the user’s browser is set to Comptibility View.

Currently rated 3.3 by 6 people

  • Currently 3.333333/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by: eladv
Posted on: 9/20/2010 at 1:54 AM
Tags:
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

How-to: Detecting IE8 with Compatibility View and general browser support.


If you decide to stop supporting all types of browsers, mainly older IE browsers, you’ll probably be required to detect the browser and it’s version using either client or server programming. Client browser detection can use viewed here. This blog entry focuses on an ASP.NET server side solution, which will allow not only to detect if the browser is supported, but on how to detect IE8 running in Compatibility View (optionally notifying the user on how to switch from this view to IE8).

The solution is quite simple - it relies on the user-agent string sent by the browser. Browsers send information to the server, one of them is HTTP_USER_AGENT, which describes the user’s browser. For example, IE browsers incorporate the keyword MSIE plus the browser’s version. So IE6 will show as MSIE 6, IE7 will show up as MSIE 7 and IE8 will show up as MSIE 8. But how will IE8 appear in Compatibility View (that is, IE7)? Apparently, the browser will send a string with MSIE 7. So, how can we tell whether this is really an IE7, or IE8 in Compatibility View? The answer relies also in the user-agent string: IE8 incorporates a new “Trident” token in the user-agent string, even in Compatibility View. So by combining a check for MSIE 7 with Trident, allows understanding that the user is running in Compatibility View.

In short, the following ASP.NET code will detect if the browser is running in Compatibility View:
bool isCompatibilityMode = (Request.UserAgent.IndexOf("MSIE 7") > -1 && Request.UserAgent.IndexOf("Trident") > -1);

Naturally, you may choose to refactor this code to “better looking code”, such as testing for IE first, and then testing for the major version of the browser etc’.

You can also combine this code in different scenarios: You can detect other browsers, you can block certain browsers, you can notify the users that they’re using unsupported browsers, and you can notify how to switch off Compatibility View etc’. It could also be a good practice to store the user’s decision in a Cookie, Session or some other Profile settings, in order not to process this code every time the browser makes a request.

You can read about the cause for this code in the first place in Browser Wars and Compatibility in Internet Explorer (Hebrew).

To see what your user agent is, click here.

 

Currently rated 2.4 by 7 people

  • Currently 2.428571/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by: eladv
Posted on: 9/20/2010 at 12:29 AM
Tags:
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

מלחמת הדפדפנים ובעיית התאימות של Internet Explorer

הסיפור הבא מבוסס על מקרה אמיתי... (אנגלית).


"שוד ושבר": שלא כמו במצגות פנימיות שערכנו לחברה, במחשב המנכ"ל, אפליקציית ה-Web שפיתחנו הוצגה בצורה בעייתית, מה שגרם לחוויית משתמש מפוקפקת. מבחינתנו, הבעיה הייתה ברורה וצפה מיד: המנכ"ל גלש ב-IE8 במצב "תאימות לאחור" (Compatibility View).


חברת פרופר מספקת שירותי אאוטסורסינג וייעוץ בתחום .NET לחברה מסוימת בתחום האבטחה. בין השאר אנו מפתחים אפליקציית Web, שמטרתה להיות ממשק משתמש לבעלי התפקידים השונים. האפליקציה כתובה ב- ASP.NET 4 תוך שימוש בגרפיקה עשירה מאת מעצבים מקצועיים, מרובת Themes ו-Ajax לטובת חוויית משתמש טובה, נינוחה ומהירה. בשלבים מתקדמים בפיתוח ולקראת יציאה של גרסת התנסות ללקוחות, נקראנו למנכ"ל החברה, אשר ביקש להשתמש באפליקציה כפי שהיא נמצאת בשרתי הבדיקות, ואז צצה הבעיה המדוברת - בעיית התאימות בדפדפני IE.


על מנת להבין מהו Compatibility View, כדאי לתת מספר מילים לגבי פיתוח אפליקציות Web ומלחמות הדפדפנים. פיתוח אפליקציית Web שונה מהותית מפיתוח אפליקציות רגילה, בכך שהמשתמש לא עובד עם תוכנה ייעודית המותקנת מקומית, אלא באמצעות הדפדפן. כך שחוויית המשתמש תלויה בצורה חד-משמעית בסוג הדפדפן שהוא משתמש וכמובן בגרסת הדפדפן: בדרך כלל, ככל שהדפדפן מעודכן יותר, כך חוויית המשתמש צפויה להיות עשירה יותר ומהירה יותר. אלא שהיו הרבה תהפוכות לאורך השנים, והדומיננטיות של דפדפן Microsoft Internet Explorer, עקב הימצאותו כחלק ממערכות ההפעלה מסוג Windows, גרמו למיקרוסופט עד לפני מספר שנים לנסות להכתיב לשוק סטנדרטים משלה. התוצאה: שנים רבות של פיתוח לפי דפדפני IE הדומיננטיים, גרמו לכך שאתרים רבים פשוט לא עבדו בצורה תקינה על גבי דפדפנים מתחרים. על מנת שהאפליקציה תעבוד בצורה תקינה הן על גבי IE והן על גבי דפדפנים מתחרים, נדרשו מאמצים הכרוכים לרוב הן בהוצאה כלכלית על זמן הפיתוח וההתאמה, ולעתים אף דחייה בשחרור גרסאות של אפליקציות שונות.


אך מה שהיה נראה כמו ניצחון בטוח של מיקרוסופט על המתחרים, השתנה עד לפני מספר שנים עם יציאתם של דפדפנים חזקים מתחרים (Firefox, Safari, Google Chrome ואחרים), אשר סיפקו מענה הולם לצורכי המשתמשים, בעוד מיקרוסופט זנחה את התחרות ובחרה במשך תקופה ארוכה שלא לפתח גרסאות חדשות ומתקדמות ל-IE. דוגמא פשוטה לכך היא גלישה באמצעות טאבים, שפשוט לא הייתה זמינה עד סוף 2006 (ב-IE7), בעוד שאצל המתחרים זו הייתה תכונה מובנית מזה מספר שנים. מיקרוסופט בשנים האחרונות מבינה שהיא טעתה בהזנחת המשתמשים, וחשוב מכך, בהזנחת הסטנדרטים, ועושה מאמצים רבים לפתח דפדפנים עדכניים ותחרותיים אשר תומכים בסטנדרטים העולמיים המקובלים. לראשונה ראינו זאת ביציאת IE8, אשר היה בבחינת אבן דרך משמעותית בהליכה לקראת הסטנדרטים העולמיים (אבל עדיין מרחק רב מהרצוי), ובקרוב אף ייצא IE9 שאמור להיות קפיצת דרך משמעותית, הן בתאימות לסטנדרטים והן מבחינת ביצועים.


הבעיה שמיקרוסופט הייתה צריכה להתמודד עמה, היא אותם אתרים אשר נבנו במשך שנים לפי גרסאות קודמות של IE, שכזכור, נבנו שלא לפי הסטנדרטים העולמיים. גלישה לאתרים אלה ב-IE8 עלולה לגרום להם להיות מוצגים בצורה לא תקינה, בדיוק כמו בדפדפנים המתחרים. כמו במקרים אחרים, מיקרוסופט פתרה את הבעיה על ידי שילוב של מצב "תאימות לאחור" (Compatibility View) - ובלחיצת כפתור, משתמש IE8 יכול לצפות באתר שבו הוא נמצא, כאילו הוא גולש לשם בדפדפן IE7, ולראות את האתר בצורה תקינה.


אם כן, זה היה המצב שבו היה נתון מנכ"ל החברה - הוא גלש לאפליקציה שלנו בדפדפן IE8, שהיה מכוון למצב "תאימות לאחור", ולמעשה צפה בו כאילו הוא גלש בדפדפן IE7. האפליקציה שלנו פותחה כך שתתמוך ב-IE8 וב-Firefox 3.5, על מנת שלא להשקיע בזמן פיתוח מיותר ב-IE7, ולכן לא נצפתה אצלו במחשב בצורה תקינה. בצורה פשוטה החזרנו את הדפדפן של המנכ"ל למצב IE8 והדברים הסתדרו. אך זה לא פתר את הבעיה האמיתית: משתמש ארעי עלול למצוא את עצמו בדיוק באותה סיטואציה של המנכ"ל, ולגלוש "בטעות" בדפדפן IE8 במצב IE7. גם הפתרונות התכנותיים המקובלים לכאורה, אשר אמורים "לסייע לדפדפן IE8 להבין שהוא אמור להציג את התוכן שלא במצב IE7" - לא תמיד עובדים, ולו רק בשל העובדה ש-IE8 עלול להיות מכויל לכך שאתרים פנים-ארגוניים (Intranet websites) יוצגו תמיד במצב של תאימות לאחור. יתרה מכך, ישנם משתמשים אשר עדיין גולשים בדפדפני IE6 או IE7, וחווית המשתמש שלהם צפויה להיות מאוד לא מוצלחת.


הפתרון האידאלי לכאורה היה פשוט: יש לתמוך בכל הדפדפנים. אך בפועל, זהו כנראה הפתרון ה"פחות מוצלח". משך ההשקעה בזמן פיתוח והתאמה לדפדפנים ישנים, כולל בדיקות QA ודחיית יציאתן של גרסאות - פשוט לא תמיד שווה את ההשקעה, אלא במקרים יוצאי דופן. בעולם שבו הדפדפנים מתקדמים בקצב אדיר, שאתרים מובילים בשוק מודיעים שהם יפסיקו תמיכה ב-IE ישנים (google, YouTube ו-Facebook Chat), ושמיקרוסופט בעצמה ממליצה לשדרג ל-IE8 - צריך סיבה טובה לממן המשך תמיכה ב-IE6 או IE7. למעלה מ-70% מהגולשים השונים לא עובדים בגרסאות ישנות אלה, נכון לאוגוסט 2010.


לכן, בסיכומו של דבר היו שתי אפשרויות פעולה בעבור משתמשי IE בגרסאותיו הישנות:

  1. לכלול תמיכה ב-IE7 (לגבי IE6 "ומטה" מעולם לא היה ספק, שלא תהיה תמיכה) - מה שכאמור היה גורר מאמצים בפיתוח ובבדיקות, ופותח פתח לבאגים ותחזוקה עודפת.

  2. לאתר את סוג דפדפן ה-IE של המשתמש ולפעול בהתאם:

    1. במידה ומדובר ב-IE 6/7 - לספק למשתמש מסך הסבר עם המלצה לשדרג את הדפדפן  (פתרון זה טוב גם עבור דפדפנים אחרים שאינם נתמכים באופן רשמי).

    2. במידה ומדובר ב-IE8, במצב תאימות לאחור ל-IE7 - להציג מסך למשתמש עם הסבר לגבי מצב "תאימות לאחור", הכולל המלצה לכבות מצב זה ולעבור ל-IE8, כולל הנחיות כיצד לעשות זאת.


בכל מקרה, המשתמש יוכל להחליט "על אחריותו", להמשיך בדפדפן שאיננו נתמך.


חשוב להבין שהאפשרות לספק תמיכה ל-IE7 יכולה להגיע גם בשלב מאוחר, לאחר קבלת חיווי מהמשתמשים עצמם. תמיד אפשר לקבל תגובות מהשטח ולקבל החלטה בשלב מאוחר יותר, להמשיך ולהשקיע בפיתוח והתאמה לדפדפנים ישנים יותר. עוד חשוב לציין, שההחלטה לתמוך בסוגים מסוימים של דפדפנים אל מול ההחלטה לוותר על דפדפנים אחרים, בפרט IE6/7 שהם עדיין דפדפנים נפוצים, אמורה להיות החלטה אסטרטגית ברמה הניהולית, ולא צריכה להיות החלטה של צוות הפיתוח בלבד (אם כי בהחלט יש להתייעץ עם צוות הפיתוח לגבי המשמעויות).


במקרה המדובר הבחירה בסופו של דבר הייתה לוותר על IE7, עד אשר ואם תגיע דרישה מהמשתמשים אשר תיתפס כמחייבת, ולספק הודעות מתאימות אשר יעודדו אותם לשדרג ל-IE8 או FF 3.5 ומעלה. במקרה שבו משתמש גולש במצב תאימות ל-IE7, נספק הסברים כיצד לעבור ל-IE8.


קרא כיצד לבצע לבדוק בקוד האם דפדפן ה-IE רץ במצב Compatibility View.

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by: eladv
Posted on: 9/20/2010 at 12:13 AM
Tags:
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

Threadpool threads and waiting for large number of threads to finish

This article is about waiting for a large number of ThreadPool threads to finish executing, and two exceptions that can occur in a winforms application when trying to wait for ThreadPool threads to finish. 

Long long time ago in the days of visual studio 2008  i was playing with ThreadPool trying to queue a large number of threads and waiting for them to finish. I recreated the issues I stumbled upon in the new and shiny visual studio 2010 express.I created a new windows forms application and tried out the following code:

 

private static void CreateLotsOfThreads()

{

    int numberOfThreads = 1000; // Large number of threads 

    // An array whichis global to all the threads where each thread reports

    // to a unique index when it finishes working

    ManualResetEvent[] ResetEvents = new ManualResetEvent[numberOfThreads];

    // Initialize ManualResetEvent objects with a non signaled state, causing threads

    // which execute WaitOne() on to block until the thread has finished working 

    for (int threadIndex = 0; threadIndex <numberOfThreads; threadIndex++)

        ResetEvents[threadIndex] = new ManualResetEvent(false); 

    for (int i = 0; i < numberOfThreads; i++)

    {

        // The index to set in the ResetEvents array when the current thread finishes.

        // The copy of i prevents the anonymous methods from sharing variables with the

        // outerscope (see remarks at the end of the article for more information)

        int guaranteedIndex = i; 

        // Queue ananonymous delegate for the example

        ThreadPool.QueueUserWorkItem(

            delegate

            {

                //Thread work

                Thread.Sleep(10);

                //Thread finished working

               ResetEvents[guaranteedIndex].Set();

            });

    }

    // Wait for allof the threads to finish

    WaitHandle.WaitAll(ResetEvents);

    // At this pointall the threads finished execution

}

       

When executing the above code, I received this error message:

System.NotSupportedException wasunhandled

 Message=The number of WaitHandles must be less than or equal to 64.

 

I changed the value of numberOfThreads to 64 and executed it again, what can possibly go wrong now? Well this time a different error message appeared:

System.NotSupportedException wasunhandled

 Message=WaitAll for multiple handles on a STA thread is not supported.

 

Windows Forms applications use a Single Threaded Apartment (STA) andWaitAll() supports only Multithreaded Apartment (MTA) so it cannot be usedhere, but does not matter, even if 64 threads were running my goal was to queue a much larger amount so this could not be of help anyway (And i don’t want to execute threads in batches of 64)

 

One solution to the problem is to wait for each thread individualy:

 

private void CreateAndWaitSolution1()

{

    int numberOfThreads = 1000; // Large number of threads

    ManualResetEvent[] ResetEvents = new ManualResetEvent[numberOfThreads];

 

    for (int threadIndex = 0; threadIndex <numberOfThreads; threadIndex++)

        ResetEvents[threadIndex] = new ManualResetEvent(false); 

    for (int i = 0; i < numberOfThreads; i++)

    {

        int guaranteedIndex = i; 

        ThreadPool.QueueUserWorkItem(

            delegate

            {

                Thread.Sleep(10);

               ResetEvents[guaranteedIndex].Set();

            });

   

    // Wait until allthreads set their ManualResetEvent state to signaled

    for (int i = 0; i < 1000; i++)

        ResetEvents[i].WaitOne();

    // At this pointall the threads finished execution

}

 

The above approach is simple, just iterate over the array which is global to all the threads and wait for each thread to finish. ManualResetEvent is threadsafe, and all of the instances are created before any thread is executed, so it should be pretty safe.

In the above code only the UI thread does the waiting, but it is possible to make a specific ThreadPool thread  wait for another ThreadPool thread to finishbefore it starts working, (assuming there is a dependency between the two threds),the code above allows this by using the ResetEvents array. Example:

 

ThreadPool.QueueUserWorkItem(

delegate

{

    // Make threadnumber 6 wait thread number 7 before it begins working

    if (guaranteedIndex== 5)

        ResetEvents[6].WaitOne();

    Thread.Sleep(10);                       

    ResetEvents[guaranteedIndex].Set();

});

 The above example shows how to make a specific ThreadPool thread waitfor another ThreadPool thread to finish before it begins working.

  

Back to the main subject, A different approach for waiting for threads to finish does not require the usage of ManualResetEvent, but it’s good only if threads do not depend on one another. It involves counting the number of threads which finished and periodicallychecking how many threads finished working from the main UI thread:

private void CreateAndWaitSolution2()

{

    int numberOfFinishedThreads = 0;

    int numberOfThreads = 1000; // Large number of threads

 

    for (int i = 0; i < numberOfThreads; i++)

    {

        intguaranteedIndex = i; 

        ThreadPool.QueueUserWorkItem(

            delegate

            {

                Thread.Sleep(10);

                //Atomic Increments and store

                Interlocked.Increment(ref numberOfFinishedThreads);

            });

    }

     // Wait until all threads incremented the numberOfFinishedThreads counter

    while(numberOfFinishedThreads < numberOfThreads)

        Thread.Sleep(100);

    // At this pointall the threads finished execution

}

 The above makes the ManualResetEvent array unnecessary and I assume that it saves some memory, the number of code lines  is not reduces dramatically though. 

 The Interlocked.Increment prevents a race condition which can cause two separate threads to increment the counter to the same value. The sleep duration can be tweaked to be more aggressive or less aggresive depending onthe amount of time you expect the threads to finish.

 

I was concerned about UI freeze in windows forms application so  I did a little experiment on the above code: I changed numberOfThreads to 10000 and added a textbox and a button to the

main application form, I then  executed the following in the Form load event:

 

private void Form1_Load(objectsender, EventArgs e)

{

    textBox1.Text = "working...";

    Thread thread = newThread(new ThreadStart(delegate

        {

            //Delayed start, just to make sure the form will show etc.

            Thread.Sleep(1000);

            CreateAndWaitSolution1();

            //CreateAndWaitSolution2();

            // Safelyupdate the UI thread from this thread

            this.Invoke(new MethodInvoker(delegate

            {

                textBox1.Text = "finished!";

            }));

        }));

    thread.IsBackground = true;

    thread.Start();

}

 

The form was responsive, I could drag it anywhere without lag and there was no problem pressing the button. CreateAndWaitSolution1 Finished much faster than CreateAndWaitSolution2 when both ran 10000 threads, the opposite of what i expected.  I guess Interlocked.Increment is responsible for that, it blocks threads when they try to  increment the counter value at the same time which makes the total execution time longer.

   

Some more information about Threapool: 

-  Threapool  is Good for executing many short-livedthreads, providing your application with a  pool of worker threads  that are managed by the system.

- ThreadPool threads are background threads and will not keep anapplication running after all foreground threads have exited.

- You cannot join on a threadpool thread

- You cannot assign priority to ThreadPool thread

- You cannot abort a specific ThreadPool thread

 

Remarks: 

 guaranteedIndex: Because the ThreadPoolexecutes threads “when a thread pool thread becomes available” The code insidethe anonymous delegate is executed only after the loop completes, giving eachthread the last value of i and not the value that i had when the delegate codewas put into the Threadpool queue.

Currently rated 4.0 by 1 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by: amirtal
Posted on: 5/11/2010 at 11:06 PM
Categories: .NET | Winforms
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (1) | Post RSSRSS comment feed

הכנסת null כערך ל-textbox

נושא קטן, ישן ומעצבן ששוב בזבז שעות עבודה מיותרות. בניגוד לכל הדפדפנים האחרים, כאשר מנסים להכניס לתיבת טקסט ערך null באמצעות javascript, הדפדפן IE "מגדיל ראש" שלא לצורך ובמקום לאפס את הערך למחרוזת ריקה, הוא מכניס את המחרוזת "null". מה שמפתיע יותר הוא שגם IE8, שכבר מתחיל להתקרב יותר ויותר להיות דפדפן שעובד לפי התקנים, גם הוא ממשיך עם ההתנהגות הזו. ככל הנראה הסיבה להתנהגות זו היא ש-MS רצו בזמנו להקל על התוכניתנים ולהבין מחרוזות הכתובות ללא גרשיים כמחרוזות, ופשוט שכחו להתייחס למקרה המיוחד של null. אפשר לראות בזה באג כיוון שבכל הדפדפנים האחרים זה עובד בצורה תקינה (לפחות בבדיקה מול: chrome, safari, firefox).
 
אגב, התופעה משתחזרת גם בדפדפני IE ישנים יותר, כגון IE6 ו- IE7 (אשר עדיין בשימוש בפלחים גדולים באוכלוסיה).
 
ניתן לשחזר בצורה מאוד פשוטה באמצעות דף html. פשוט להעתיק את שתי השורות הבאות ולהריץ:

<input type='text' id='txt' />
<input type='button' onclick="document.getElementById('txt').value=null;" value='insert null' />

 
התיקון פשוט מאוד.סה"כ יש להחליף את null במחרוזת ריקה:
 

<input type='text' id='txt' />
<input type='button' onclick="document.getElementById('txt').value='';" value='insert null' />

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by: eladv
Posted on: 11/17/2009 at 11:09 PM
Tags: , ,
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

המדריך לדו"חות: איך חברה מרוויחה ואין לה כסף?

חלק שני של המאמר מאת אריאל פטל, חבר קרוב ובעל מקצוע מהדרגה הראשונה... מומלץ לקרוא...

 

מה מייצג דו"ח רווח והפסד ומדוע צריך דו"ח תזרים מזומנים, מה למשק בית ודו"ח כספי של חברה, ואיך חברה יכולה להרוויח בספרים, אך להישאר ללא מזומנים? פרק שני במדריך

 

מצ"ב קישור לכתבה ב-ynet.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by: uris
Posted on: 10/21/2009 at 9:51 PM
Tags: , , , , ,
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

Visual Studio 2008 Design View Freezing Solved

Recently we had an issue with VS2008 freezing (stuck, not responding... you name it...) when you try to switch to design-view of a web page (aspx).

Since we merely changed the markup lately, it's been quite annoying.

This issue was very time consuming as the web offered no solution for this behavior (the solutions offered weren't helpful - at least for our case).Cry

 

Having a tight deadline in our project, we really had to solve this issue quickly and decided to use brute-force by tearing the Master Page (which seemed to be causing this) apart for finding the problematic markup.

I repeatedly removed blocks of markup and tried to switch to design-view after each block was removed.

Most of the time switching to design-view caused the devenv.exe (VS2008) to stop responding and I had to kill the process (via the Task Manager).

After a while, I have found the markup that was preventing me from switching to design-view.

 

For what it's worth, the markup is presented here: (Very weird, can't see why this should be problematic).

<asp:Label ID="lblOrganisation" CssClass="changeOrganization" runat="server" Font-Names="Arial"

Font-Size="12pt" Height="23px" Text="Switch Organization:" meta:resourcekey="lblOrganisationResource1">

</asp:Label>

Shall you have another solution or an explanation why Height="23px" (the block that I removed) should cause this, please leave a comment.

 

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by: uris
Posted on: 10/21/2009 at 9:12 PM
Tags: , , , , , ,
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (1) | Post RSSRSS comment feed

איך גורמים ל-Apple MacBook Air SuperDrive לחזור ולהופיע בויסטה

משום מה פתאום לא הופיע ב"מחשב שלי" כונן הדיסקים החיצוני של המק בוק איר שלי...

חיפשתי רבות באינטרנט עד שמצאתי פתרון הולם והאמת החיפוש היה שווה... במקום להתקין הכל (אבל הכל) מחדש (כפי שהציעו בהרבה פורומים) קיבלתי פיתרון אלגנטי שעוקף את הבעיה בזריזות ומאפשר לחזור ולהנות מהכונן אפילו בלי לעשות restart.

המקור הוא פה:

http://discussions.apple.com/thread.jspa?threadID=1741817&tstart=-1  (מי שכתב את הפתרון הוא sieken)

 

השלבים הם פשוטים:

1. להיכנס לניהול מערכת (לחיצה על המחשב שלי עם הלחצן הימני של העכבר).

2. בוחרים עם הלחצן הימני של העכבר את External SuperDrive ובוחרים ב-Update Driver (עדכון מנהל התקן).

3. באשף שנפתח בוחרים שלא לחפש באופן אוטומטי אלא להתקין באופן ידני מנהל התקן שנבחר (Install from specific location -> Don't search).

4. בוחרים ב-USB Mass Storage Device ולוחצים על "סיום".

5. לאחר שהאשף נסגר בוחרים שוב עדכון מנהל התקן (שימו לב שהכונן שינה את שמו ל-USB Mass Storage Device).

6. חוזרים על שלב 3.

7. חוזרים על שלב 4 רק שהפעם חוזרים למנהל ההתקן המקורי "Apple SuperDrive" ולוחצים על "סיום".

 

מקווה שעזרתי לנפש אחת או שתיים - לי זה חסך כמה שעות מיגעות מאוד.

 

בהצלחה,

אורי.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by: uris
Posted on: 10/11/2009 at 4:11 PM
Tags: , , , , , , ,
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

איך קוראים דו"ח כספי? המדריך לשפת המספרים

מאמר מאת אריאל פטל, חבר קרוב ובעל מקצוע מהדרגה הראשונה... מומלץ לקרוא...

 

עונת הדו"חות של הרבעון ה-3 מתחילה בימים אלה, ומציפה אותנו שוב במספרים חסרי משמעות. האם הפעם נבין קצת יותר מה עושים עם כספי החסכונות שלנו או מה ביצועי החברות בהן השקענו בבורסה? המדריך לקריאת דו"חות כספיים - חלק ראשון.

 

מצ"ב קישור לכתבה ב-ynet.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by: uris
Posted on: 10/10/2009 at 12:12 AM
Tags: , , , , ,
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (0) | Post RSSRSS comment feed

קוד מקור לטובת דיבאג

חדשה ישנה אבל לא בהכרח מוכרת ונפוצה היא שמיקרוסופט שחררו את קוד המקור של דוטנט 3.5. המשמעות היא שניתן לבצע דיבאג בעזרת קוד המקור של מיקרוסופט ופחות להשתמש בטכניקות עקיפות כגון Reflector (המצוין). להלן הסבר קצר כיצד להפעיל אפשרות זו:

יש לפתוח את האפשרויות ב- Tools->Options->Debugging ולבטל את Just My Code ולשפעל את Enable source server support.

יש לקנפג את המקום ממנו ייטענו ה-debugging symbols ולאן יישמרו (Tools->Options->Debugging->Symbols):

הכתובת היא: http://referencesource.microsoft.com/symbols.

הערה: החלון עשוי להראות שונה בין גרסאות ה-Visual Studio השונות.

כאשר מגיעים לקטע שאותו מעוניינים לדבג (framework, לא קוד שלנו), ב-call stack בוחרים ב-Load Symbols.


  

לאחר מספר שניות צפויה להופיע אזהרת copy rights. אם ההערה חוזרת שוב ושוב, ניתן להוריד תיקון כאן. אם לא מופיעה הודעת אזהרה, כדאי לעצור את הדיבאג ואחר כך לנסות שוב.

כפי שניתן לראות, ה-Symbols נטענו עבור הקבצים המבוקשים וכעת ניתן לבצע Step Into.

עד כאן היו צעדים ראשונים בנושא. למעשה, יש פירוט נרחב למדי ונושאים מתקדמים שעליהם ניתן לקרוא כאן.

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by: eladv
Posted on: 4/11/2009 at 10:14 AM
Actions: E-mail | Kick it! | DZone it! | del.icio.us
Post Information: Permalink | Comments (1) | Post RSSRSS comment feed