Tuesday, February 18, 2014

asp.net, run few methods / functions simultaneously

    Sub A()
        Threading.Thread.Sleep(2000)
        Title = "hello"
    End Sub


sub Page_Load (o as object, e as eventargs)

        Dim t() As Threading.Tasks.Task = {Threading.Tasks.Task.Factory.StartNew(Sub() A()),
                                            Threading.Tasks.Task.Factory.StartNew(Sub() A()),
                                            Threading.Tasks.Task.Factory.StartNew(Sub() A()),
                                            Threading.Tasks.Task.Factory.StartNew(Sub() A()),
                                            Threading.Tasks.Task.Factory.StartNew(Sub() A())
                                            }
        Threading.Tasks.Task.WaitAll(t)

       Response.Write("Tasks done")

end Sub

"A" Method takes 2 seconds to run. run five "A" methods at the same time, will also take about 2 seconds in total, instead of 10 seconds if run by queue. easy and simple. useful for binding/populating dropdownlist values for example.

Sunday, February 16, 2014

Check if client re-submits asp.net form

<%@ Page Language="VB" AutoEventWireup="false" %>

<script runat="server">

    Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
       
        If Not IsPostBack Then
            'First time page loads, set the count to 1 and save it to session
            Dim g = Guid.NewGuid()
            ViewState("refresh") = g
            ViewState("refreshcount") = 1
            Dim d As Dictionary(Of Guid, Object()) = Session("refresh")
            If d Is Nothing Then
                d = New Dictionary(Of Guid, Object())
                Session("refresh") = d
            End If
            d(g) = {1, Now}
        Else
            Dim d As Dictionary(Of Guid, Object()) = Session("refresh")
            If d IsNot Nothing Then
                SyncLock d
                    Dim g As Guid = ViewState("refresh")
                    Dim i As Integer = ViewState("refreshcount")
                    If Not d.ContainsKey(g) Then
                        Response.Write("Key not found")
                        Response.End()
                    End If
                    Dim item = d.FirstOrDefault(Function(a) a.Key = g)
                    Dim dt As DateTime = item.Value(1)
                    If dt.AddMinutes(30) < Now Then
                        d.Remove(g)
                        Response.Write("Key expired after 30 minutes")
                        Response.End()
                    End If
                    If i <> item.Value(0) Then 'compare the refresh count posted from viewstate vs the one in session
                        d.Remove(g)
                        Response.Write("Form post refresh not allowed")
                        Response.End()
                    Else
                        ViewState("refreshcount") += 1
                        item.Value(0) += 1
                        item.Value(1) = Now
                    End If
                End SyncLock
            End If
        End If
        Title = Guid.NewGuid.ToString() 'to test if the long running process below actually runs in another thread, therefore not blocking page rendering
        System.Threading.Tasks.Task.Factory.StartNew(Sub() ClearExpiredRefreshDictionary())
    End Sub



    Private Sub ClearExpiredRefreshDictionary()

        Dim d As Dictionary(Of Guid, Object()) = Session("refresh")
        If d IsNot Nothing Then
            SyncLock d
                Dim q = (From a In d Where CType(a.Value(1), DateTime).AddMinutes(30) < Now Select a)
                For Each a In q
                    d.Remove(a.Key)
                Next
                Threading.Thread.Sleep(3000)
            End SyncLock
        End If

    End Sub
   
</script>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
   
    </div>
        <asp:Button ID="Button1" runat="server" Text="Button" />
        <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
    </form>
</body>
</html>