我有这个让我疯狂的问题。
我有一个项目要在星期四之前交付。基本上是一个由三个组件组成的应用程序,它们在WCF中相互通信。
我有一个控制台应用程序和一个Windows窗体应用程序。控制台应用程序是连接到数据库的服务器。您可以通过Windows窗体客户端向其添加记录,该窗体客户端通过WCF与服务器连接。
客户代码:
namespace BankAdministratorClient
{
[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Single, UseSynchronizationContext = false)]
public partial class Form1 : Form, BankServverReference.BankServerCallback
{
private BankServverReference.BankServerClient server = null;
private SynchronizationContext interfaceContext = null;
public Form1()
{
InitializeComponent();
interfaceContext = SynchronizationContext.Current;
server = new BankServverReference.BankServerClient(new InstanceContext(this), "TcpBinding");
server.Open();
server.Subscribe();
refreshGridView("");
}
public void refreshClients(string s)
{
SendOrPostCallback callback = delegate(object state)
{ refreshGridView(s); };
interfaceContext.Post(callback, s);
}
public void refreshGridView(string s)
{
try
{
userGrid.DataSource = server.refreshDatabaseConnection().Tables[0];
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void buttonAdd_Click(object sender, EventArgs e)
{
server.addNewAccount(Int32.Parse(inputPIN.Text), Int32.Parse(inputBalance.Text));
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
try
{
server.Unsubscribe();
server.Close();
}catch{}
}
}
}
服务器的代码:
namespace SSRfinal_tcp
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(MessageHandler.dataStamp("The server is starting up"));
using (ServiceHost server = new ServiceHost(typeof(BankServer)))
{
server.Open();
Console.WriteLine(MessageHandler.dataStamp("The server is running"));
Console.ReadKey();
}
}
}
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single, InstanceContextMode = InstanceContextMode.PerCall, IncludeExceptionDetailInFaults = true)]
public class BankServer : IBankServerService
{
private static DatabaseLINQConnectionDataContext database = new DatabaseLINQConnectionDataContext();
private static List<IBankServerServiceCallback> subscribers = new List<IBankServerServiceCallback>();
public void Subscribe()
{
try
{
IBankServerServiceCallback callback = OperationContext.Current.GetCallbackChannel<IBankServerServiceCallback>();
if (!subscribers.Contains(callback))
subscribers.Add(callback);
Console.WriteLine(MessageHandler.dataStamp("A new Bank Administrator has connected"));
}
catch
{
Console.WriteLine(MessageHandler.dataStamp("A Bank Administrator has failed to connect"));
}
}
public void Unsubscribe()
{
try
{
IBankServerServiceCallback callback = OperationContext.Current.GetCallbackChannel<IBankServerServiceCallback>();
if (subscribers.Contains(callback))
subscribers.Remove(callback);
Console.WriteLine(MessageHandler.dataStamp("A Bank Administrator has been signed out from the connection list"));
}
catch
{
Console.WriteLine(MessageHandler.dataStamp("A Bank Administrator has failed to sign out from the connection list"));
}
}
public DataSet refreshDatabaseConnection()
{
var q = from a in database.GetTable<Account>()
select a;
DataTable dt = q.toTable(rec => new object[] { q });
DataSet data = new DataSet();
data.Tables.Add(dt);
Console.WriteLine(MessageHandler.dataStamp("A Bank Administrator has requested a database data listing refresh"));
return data;
}
public void addNewAccount(int pin, int balance)
{
Account acc = new Account()
{
PIN = pin,
Balance = balance,
IsApproved = false
};
database.Accounts.InsertOnSubmit(acc);
database.SubmitChanges();
database.addNewAccount(pin, balance, false);
subscribers.ForEach(delegate(IBankServerServiceCallback callback)
{
callback.refreshClients("New operation is pending approval.");
});
}
}
}
这非常简单,适用于单个窗口。但是,当您打开客户端窗口的多个实例并尝试添加新记录时,执行插入操作的窗口会因ExecuteReader错误而崩溃,并且“需要一个开放且可用的连接。连接的当前状态正在连接”bla bla东西。我不知道是怎么回事。请指教。
答案 0 :(得分:1)
这很可能是因为您宣布您的DatabaseLINQConnectionDataContext
是静态的。这是一个大禁忌!当变量是静态的时,它在所有线程(请求)之间共享。这是一个很大的问题,因为DataContext存储了有关您所做的更改的工作单元信息,请您进行更改。
为每个客户端初始化一个DatabaseLINQConnectionDataContext
,否则您将遇到类似这样的错误。尝试在数据访问周围的database
块中初始化using
。