その日に送信する必要のあるメールのリストを表示するウェブアプリがあります。ユーザーは送信する電子メールを選択し、ボタンをクリックしてそれらを生成できます。[送信]ボタンをクリックすると、電子メールを生成する別のスレッドでプロセスが開始され、一時フォルダーを削除してプロセスがクリーンアップされます。プロセスが終了すると、リピーターがリバウンドされてユーザーのビューが更新され、送信されたばかりの電子メールが削除されて、再度送信されないようになります。
私の問題は、2番目のスレッドからtempフォルダーを削除すると、UIが新しいRepeaterデータで更新されないことです。フォルダ自体ではなくフォルダ内のファイルを削除しただけで正しく更新され、2番目のスレッドではなく元のスレッドでフォルダの削除を実行した場合も正しく更新されます。
新しいスレッドコード
Dim t as Thread = New Thread(New ThreadStart(AddressOf EmailLetters))
t.Start()
フォルダコードを削除する
Dim fs = Server.CreateObject("Scripting.FileSystemObject")
fs.DeleteFolder(Server.MapPath(".") + "\tmpEmailFiles")
別のスレッドのフォルダーを削除すると、UIが更新されて新しいリピーター値が表示されないのはなぜですか?
編集
問題を示すサンプルコードを次に示します。少し面倒な場合は申し訳ありませんが、問題を特定するのに役立つ簡単なものが必要でした。
ボタンをクリックすると、スレッドが開始され、JavaScriptロードスクリプトの実行が開始され、10秒ごとにPostBackが実行されます。各ポストバックは、スレッドが完了したかどうかをチェックし、結果を示すステータスラベルを更新します。バックグラウンドスレッド内からフォルダーを削除すると、ステータスラベルの最終更新が行われません。DeleteFolder呼び出しを削除すると、削除されます。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%@ Import Namespace="System.Threading" %>
<%@ Page Language="VB" Debug="true" %>
<%@ Implements Interface="System.Web.UI.IPostBackEventHandler" %>
<SCRIPT language="vb" runat="server">
Sub Page_Load(Src As Object, e As EventArgs)
End Sub
Public Sub Test(src as Object, e as EventArgs)
Dim t as Thread = New Thread(New ThreadStart(AddressOf TestWorker))
t.Start()
Session("BackgroundThread") = t
End Sub
Public Sub TestWorker()
' 30 Second Delay
System.Threading.Thread.Sleep(30000)
Dim root as String = Server.MapPath(".")
Dim fs = Server.CreateObject("Scripting.FileSystemObject")
If Not fs.FolderExists(root + "\Test") Then fs.CreateFolder(root + "\Test")
fs.DeleteFolder(root + "\Test")
ErrMsg.Text = "Start: " + DateTime.Now.ToString()
End Sub
Public Sub RaisePostBackEvent(ByVal eventArgument As String) _
Implements IPostBackEventHandler.RaisePostBackEvent
If Session("BackgroundThread") is Nothing Then
Exit Sub
End If
Dim t as Thread = CType(Session("BackgroundThread"), Thread)
If t.ThreadState = ThreadState.Stopped Then
ErrMsg.Text = "Done: " + DateTime.Now.ToString()
Session("BackgroundThread") = Nothing
Else
ErrMsg.Text = "Processing: " + DateTime.Now.ToString() + " - " + t.ThreadState.ToString()
End If
End Sub
</SCRIPT>
<HTML>
<HEAD>
<SCRIPT language="javascript">
//<!--
function onLoad()
{
if(<%= IIF(Session("BackgroundThread") is Nothing, "false", "true") %>)
{
toggleLoading();
setTimeout("<%= Page.ClientScript.GetPostBackEventReference(Me, "") %>", 10000);
}
}
function toggleLoading(){
document.getElementById('imgLoading').style.display = 'block';
setTimeout("document.images['imgLoading'].src='images/loading.gif'", 100);
}
// -->
</SCRIPT>
</HEAD>
<BODY OnLoad="onLoad();">
<FORM runat="server">
<ASP:Button runat="server" Text="Test" OnClick="Test" onClientClick="javascript: toggleLoading();" />
<ASP:Label runat="server" Id="ErrMsg" />
<IMG id="imgLoading" src="images/loading.gif" style="display: none;" />
</FORM>
</BODY>
</HTML>